فهرست منبع

提交餐桌码代码

qmj 1 ماه پیش
والد
کامیت
4f803abe5b
100فایلهای تغییر یافته به همراه4523 افزوده شده و 17696 حذف شده
  1. 23 1
      .claude/settings.local.json
  2. 193 0
      .claude/skills/speckit-analyze/SKILL.md
  3. 304 0
      .claude/skills/speckit-checklist/SKILL.md
  4. 186 0
      .claude/skills/speckit-clarify/SKILL.md
  5. 89 0
      .claude/skills/speckit-constitution/SKILL.md
  6. 207 0
      .claude/skills/speckit-implement/SKILL.md
  7. 154 0
      .claude/skills/speckit-plan/SKILL.md
  8. 307 0
      .claude/skills/speckit-specify/SKILL.md
  9. 200 0
      .claude/skills/speckit-tasks/SKILL.md
  10. 38 0
      .claude/skills/speckit-taskstoissues/SKILL.md
  11. 31 30
      .gitignore
  12. 10 0
      .specify/init-options.json
  13. 7 0
      .specify/integration.json
  14. 18 0
      .specify/integrations/claude.manifest.json
  15. 23 0
      .specify/integrations/claude/scripts/update-context.ps1
  16. 28 0
      .specify/integrations/claude/scripts/update-context.sh
  17. 18 0
      .specify/integrations/speckit.manifest.json
  18. 50 0
      .specify/memory/constitution.md
  19. 148 0
      .specify/scripts/powershell/check-prerequisites.ps1
  20. 268 0
      .specify/scripts/powershell/common.ps1
  21. 378 0
      .specify/scripts/powershell/create-new-feature.ps1
  22. 61 0
      .specify/scripts/powershell/setup-plan.ps1
  23. 513 0
      .specify/scripts/powershell/update-agent-context.ps1
  24. 28 0
      .specify/templates/agent-file-template.md
  25. 40 0
      .specify/templates/checklist-template.md
  26. 50 0
      .specify/templates/constitution-template.md
  27. 104 0
      .specify/templates/plan-template.md
  28. 128 0
      .specify/templates/spec-template.md
  29. 251 0
      .specify/templates/tasks-template.md
  30. 30 0
      CLAUDE.md
  31. 299 0
      docs/superpowers/plans/2026-04-30-merchant-billing-mdid-filter.md
  32. 170 0
      docs/superpowers/specs/2026-04-28-multi-country-expansion-design.md
  33. 121 0
      docs/superpowers/specs/2026-04-30-qr-table-ordering-design.md
  34. 0 3
      foodie_sj_vue/.browserslistrc
  35. 0 4
      foodie_sj_vue/.env.development
  36. 0 3
      foodie_sj_vue/.env.production
  37. 0 3
      foodie_sj_vue/.env.test
  38. 0 23
      foodie_sj_vue/.gitignore
  39. 0 19
      foodie_sj_vue/README.md
  40. 0 5
      foodie_sj_vue/babel.config.js
  41. 0 19
      foodie_sj_vue/jsconfig.json
  42. 0 10568
      foodie_sj_vue/package-lock.json
  43. 0 34
      foodie_sj_vue/package.json
  44. BIN
      foodie_sj_vue/public/favicon.ico
  45. 0 17
      foodie_sj_vue/public/index.html
  46. 0 10
      foodie_sj_vue/src/App.vue
  47. 0 56
      foodie_sj_vue/src/api/fenlei.js
  48. 0 90
      foodie_sj_vue/src/api/food.js
  49. 0 61
      foodie_sj_vue/src/api/geocoding.js
  50. 0 51
      foodie_sj_vue/src/api/index.js
  51. 0 37
      foodie_sj_vue/src/api/loding.js
  52. 0 59
      foodie_sj_vue/src/api/promotion.js
  53. 0 59
      foodie_sj_vue/src/api/quanyi.js
  54. 0 59
      foodie_sj_vue/src/api/review.js
  55. 0 102
      foodie_sj_vue/src/api/store.js
  56. BIN
      foodie_sj_vue/src/assets/bag.jpg
  57. BIN
      foodie_sj_vue/src/assets/ddlan.png
  58. BIN
      foodie_sj_vue/src/assets/ktixian.png
  59. BIN
      foodie_sj_vue/src/assets/logo.png
  60. BIN
      foodie_sj_vue/src/assets/toux.png
  61. BIN
      foodie_sj_vue/src/assets/zshour.png
  62. 0 33
      foodie_sj_vue/src/components/Aside.vue
  63. 0 48
      foodie_sj_vue/src/components/Header.vue
  64. 0 308
      foodie_sj_vue/src/components/googlemap.vue
  65. 0 199
      foodie_sj_vue/src/components/googmap.vue
  66. 0 59
      foodie_sj_vue/src/components/i18n.vue
  67. 0 349
      foodie_sj_vue/src/lang/en.js
  68. 0 66
      foodie_sj_vue/src/lang/index.js
  69. 0 349
      foodie_sj_vue/src/lang/tw.js
  70. 0 349
      foodie_sj_vue/src/lang/vi.js
  71. 0 350
      foodie_sj_vue/src/lang/zh.js
  72. 0 26
      foodie_sj_vue/src/main.js
  73. 0 190
      foodie_sj_vue/src/router/gloable.css
  74. 0 61
      foodie_sj_vue/src/router/index.js
  75. 0 30
      foodie_sj_vue/src/router/jsencrypt.js
  76. 0 76
      foodie_sj_vue/src/router/request.js
  77. 0 3
      foodie_sj_vue/src/utils/Bus.js
  78. 0 6
      foodie_sj_vue/src/utils/errorCode.js
  79. 0 13
      foodie_sj_vue/src/utils/i18n.js
  80. 0 233
      foodie_sj_vue/src/utils/ruoyi.js
  81. 0 119
      foodie_sj_vue/src/views/AboutView.vue
  82. 0 555
      foodie_sj_vue/src/views/AcidrollingActual.vue
  83. 0 657
      foodie_sj_vue/src/views/AcidrollingCapacity.vue
  84. 0 208
      foodie_sj_vue/src/views/AcidrollingPlan.vue
  85. 0 46
      foodie_sj_vue/src/views/Manage.vue
  86. 0 455
      foodie_sj_vue/src/views/Promotion.vue
  87. 0 661
      foodie_sj_vue/src/views/Quanyi.vue
  88. 0 307
      foodie_sj_vue/src/views/Review.vue
  89. 0 578
      foodie_sj_vue/src/views/index.vue
  90. 0 11
      foodie_sj_vue/vue.config.js
  91. BIN
      req_image.png
  92. 12 0
      ruoyi-admin/pom.xml
  93. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/app/order/MyTestController.java
  94. 2 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java
  95. 1 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderRatingController.java
  96. 1 0
      ruoyi-admin/src/main/java/com/ruoyi/app/order/PosReviewController.java
  97. 5 5
      ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java
  98. 4 4
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java
  99. 1 1
      ruoyi-admin/src/main/java/com/ruoyi/app/pay/WalletController.java
  100. 21 27
      ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java

+ 23 - 1
.claude/settings.local.json

@@ -1,9 +1,31 @@
 {
   "permissions": {
     "allow": [
+      "Bash(*)",
       "mcp__ide__getDiagnostics",
       "Read(//mnt/e/QtwCode/foodie/**)",
-      "Bash(cat .gitignore)"
+      "Bash(cat .gitignore)",
+      "mcp__zai-mcp-server__extract_text_from_screenshot",
+      "mcp__zai-mcp-server__analyze_image",
+      "mcp__chrome_mcp_server__chrome_navigate",
+      "Bash(xargs grep *)",
+      "Bash(bash *)",
+      "Bash(echo \".superpowers/\")",
+      "Bash(sort -u -o \"E:\\\\QtwCode\\\\foodie\\\\foodie_server\\\\.gitignore\" \"E:\\\\QtwCode\\\\foodie\\\\foodie_server\\\\.gitignore\")",
+      "mcp__chrome_mcp_server__chrome_screenshot",
+      "mcp__chrome_mcp_server__chrome_computer",
+      "WebSearch",
+      "mcp__web-search-prime__web_search_prime",
+      "mcp__zread__read_file",
+      "mcp__web-reader__webReader",
+      "Read(//c/Users/qmj/.claude/**)",
+      "Bash(npm view *)",
+      "Bash(npx playwright *)",
+      "Bash(powershell -ExecutionPolicy Bypass -File \".specify/scripts/powershell/setup-plan.ps1\" -Json)",
+      "Bash(grep -E \"\\\\.\\(json|js|ts|jsx|tsx|sql|py|java|go\\)$\")",
+      "Bash(powershell -ExecutionPolicy Bypass -File \".specify/scripts/powershell/check-prerequisites.ps1\" -Json)",
+      "Bash(powershell -ExecutionPolicy Bypass -File \".specify/scripts/powershell/check-prerequisites.ps1\" -Json -RequireTasks -IncludeTasks)",
+      "Bash(mvn compile *)"
     ]
   }
 }

+ 193 - 0
.claude/skills/speckit-analyze/SKILL.md

@@ -0,0 +1,193 @@
+---
+name: "speckit-analyze"
+description: "Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation."
+argument-hint: "Optional focus areas for analysis"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/analyze.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Goal
+
+Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/speckit.tasks` has successfully produced a complete `tasks.md`.
+
+## Operating Constraints
+
+**STRICTLY READ-ONLY**: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).
+
+**Constitution Authority**: The project constitution (`.specify/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/speckit.analyze`.
+
+## Execution Steps
+
+### 1. Initialize Analysis Context
+
+Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths:
+
+- SPEC = FEATURE_DIR/spec.md
+- PLAN = FEATURE_DIR/plan.md
+- TASKS = FEATURE_DIR/tasks.md
+
+Abort with an error message if any required file is missing (instruct the user to run missing prerequisite command).
+For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+### 2. Load Artifacts (Progressive Disclosure)
+
+Load only the minimal necessary context from each artifact:
+
+**From spec.md:**
+
+- Overview/Context
+- Functional Requirements
+- Success Criteria (measurable outcomes — e.g., performance, security, availability, user success, business impact)
+- User Stories
+- Edge Cases (if present)
+
+**From plan.md:**
+
+- Architecture/stack choices
+- Data Model references
+- Phases
+- Technical constraints
+
+**From tasks.md:**
+
+- Task IDs
+- Descriptions
+- Phase grouping
+- Parallel markers [P]
+- Referenced file paths
+
+**From constitution:**
+
+- Load `.specify/memory/constitution.md` for principle validation
+
+### 3. Build Semantic Models
+
+Create internal representations (do not include raw artifacts in output):
+
+- **Requirements inventory**: For each Functional Requirement (FR-###) and Success Criterion (SC-###), record a stable key. Use the explicit FR-/SC- identifier as the primary key when present, and optionally also derive an imperative-phrase slug for readability (e.g., "User can upload file" → `user-can-upload-file`). Include only Success Criteria items that require buildable work (e.g., load-testing infrastructure, security audit tooling), and exclude post-launch outcome metrics and business KPIs (e.g., "Reduce support tickets by 50%").
+- **User story/action inventory**: Discrete user actions with acceptance criteria
+- **Task coverage mapping**: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases)
+- **Constitution rule set**: Extract principle names and MUST/SHOULD normative statements
+
+### 4. Detection Passes (Token-Efficient Analysis)
+
+Focus on high-signal findings. Limit to 50 findings total; aggregate remainder in overflow summary.
+
+#### A. Duplication Detection
+
+- Identify near-duplicate requirements
+- Mark lower-quality phrasing for consolidation
+
+#### B. Ambiguity Detection
+
+- Flag vague adjectives (fast, scalable, secure, intuitive, robust) lacking measurable criteria
+- Flag unresolved placeholders (TODO, TKTK, ???, `<placeholder>`, etc.)
+
+#### C. Underspecification
+
+- Requirements with verbs but missing object or measurable outcome
+- User stories missing acceptance criteria alignment
+- Tasks referencing files or components not defined in spec/plan
+
+#### D. Constitution Alignment
+
+- Any requirement or plan element conflicting with a MUST principle
+- Missing mandated sections or quality gates from constitution
+
+#### E. Coverage Gaps
+
+- Requirements with zero associated tasks
+- Tasks with no mapped requirement/story
+- Success Criteria requiring buildable work (performance, security, availability) not reflected in tasks
+
+#### F. Inconsistency
+
+- Terminology drift (same concept named differently across files)
+- Data entities referenced in plan but absent in spec (or vice versa)
+- Task ordering contradictions (e.g., integration tasks before foundational setup tasks without dependency note)
+- Conflicting requirements (e.g., one requires Next.js while other specifies Vue)
+
+### 5. Severity Assignment
+
+Use this heuristic to prioritize findings:
+
+- **CRITICAL**: Violates constitution MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality
+- **HIGH**: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion
+- **MEDIUM**: Terminology drift, missing non-functional task coverage, underspecified edge case
+- **LOW**: Style/wording improvements, minor redundancy not affecting execution order
+
+### 6. Produce Compact Analysis Report
+
+Output a Markdown report (no file writes) with the following structure:
+
+## Specification Analysis Report
+
+| ID | Category | Severity | Location(s) | Summary | Recommendation |
+|----|----------|----------|-------------|---------|----------------|
+| A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version |
+
+(Add one row per finding; generate stable IDs prefixed by category initial.)
+
+**Coverage Summary Table:**
+
+| Requirement Key | Has Task? | Task IDs | Notes |
+|-----------------|-----------|----------|-------|
+
+**Constitution Alignment Issues:** (if any)
+
+**Unmapped Tasks:** (if any)
+
+**Metrics:**
+
+- Total Requirements
+- Total Tasks
+- Coverage % (requirements with >=1 task)
+- Ambiguity Count
+- Duplication Count
+- Critical Issues Count
+
+### 7. Provide Next Actions
+
+At end of report, output a concise Next Actions block:
+
+- If CRITICAL issues exist: Recommend resolving before `/speckit.implement`
+- If only LOW/MEDIUM: User may proceed, but provide improvement suggestions
+- Provide explicit command suggestions: e.g., "Run /speckit.specify with refinement", "Run /speckit.plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'"
+
+### 8. Offer Remediation
+
+Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.)
+
+## Operating Principles
+
+### Context Efficiency
+
+- **Minimal high-signal tokens**: Focus on actionable findings, not exhaustive documentation
+- **Progressive disclosure**: Load artifacts incrementally; don't dump all content into analysis
+- **Token-efficient output**: Limit findings table to 50 rows; summarize overflow
+- **Deterministic results**: Rerunning without changes should produce consistent IDs and counts
+
+### Analysis Guidelines
+
+- **NEVER modify files** (this is read-only analysis)
+- **NEVER hallucinate missing sections** (if absent, report them accurately)
+- **Prioritize constitution violations** (these are always CRITICAL)
+- **Use examples over exhaustive rules** (cite specific instances, not generic patterns)
+- **Report zero issues gracefully** (emit success report with coverage statistics)
+
+## Context
+
+$ARGUMENTS

+ 304 - 0
.claude/skills/speckit-checklist/SKILL.md

@@ -0,0 +1,304 @@
+---
+name: "speckit-checklist"
+description: "Generate a custom checklist for the current feature based on user requirements."
+argument-hint: "Domain or focus area for the checklist"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/checklist.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## Checklist Purpose: "Unit Tests for English"
+
+**CRITICAL CONCEPT**: Checklists are **UNIT TESTS FOR REQUIREMENTS WRITING** - they validate the quality, clarity, and completeness of requirements in a given domain.
+
+**NOT for verification/testing**:
+
+- ❌ NOT "Verify the button clicks correctly"
+- ❌ NOT "Test error handling works"
+- ❌ NOT "Confirm the API returns 200"
+- ❌ NOT checking if code/implementation matches the spec
+
+**FOR requirements quality validation**:
+
+- ✅ "Are visual hierarchy requirements defined for all card types?" (completeness)
+- ✅ "Is 'prominent display' quantified with specific sizing/positioning?" (clarity)
+- ✅ "Are hover state requirements consistent across all interactive elements?" (consistency)
+- ✅ "Are accessibility requirements defined for keyboard navigation?" (coverage)
+- ✅ "Does the spec define what happens when logo image fails to load?" (edge cases)
+
+**Metaphor**: If your spec is code written in English, the checklist is its unit test suite. You're testing whether the requirements are well-written, complete, unambiguous, and ready for implementation - NOT whether the implementation works.
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Execution Steps
+
+1. **Setup**: Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json` from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS list.
+   - All file paths must be absolute.
+   - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+2. **Clarify intent (dynamic)**: Derive up to THREE initial contextual clarifying questions (no pre-baked catalog). They MUST:
+   - Be generated from the user's phrasing + extracted signals from spec/plan/tasks
+   - Only ask about information that materially changes checklist content
+   - Be skipped individually if already unambiguous in `$ARGUMENTS`
+   - Prefer precision over breadth
+
+   Generation algorithm:
+   1. Extract signals: feature domain keywords (e.g., auth, latency, UX, API), risk indicators ("critical", "must", "compliance"), stakeholder hints ("QA", "review", "security team"), and explicit deliverables ("a11y", "rollback", "contracts").
+   2. Cluster signals into candidate focus areas (max 4) ranked by relevance.
+   3. Identify probable audience & timing (author, reviewer, QA, release) if not explicit.
+   4. Detect missing dimensions: scope breadth, depth/rigor, risk emphasis, exclusion boundaries, measurable acceptance criteria.
+   5. Formulate questions chosen from these archetypes:
+      - Scope refinement (e.g., "Should this include integration touchpoints with X and Y or stay limited to local module correctness?")
+      - Risk prioritization (e.g., "Which of these potential risk areas should receive mandatory gating checks?")
+      - Depth calibration (e.g., "Is this a lightweight pre-commit sanity list or a formal release gate?")
+      - Audience framing (e.g., "Will this be used by the author only or peers during PR review?")
+      - Boundary exclusion (e.g., "Should we explicitly exclude performance tuning items this round?")
+      - Scenario class gap (e.g., "No recovery flows detected—are rollback / partial failure paths in scope?")
+
+   Question formatting rules:
+   - If presenting options, generate a compact table with columns: Option | Candidate | Why It Matters
+   - Limit to A–E options maximum; omit table if a free-form answer is clearer
+   - Never ask the user to restate what they already said
+   - Avoid speculative categories (no hallucination). If uncertain, ask explicitly: "Confirm whether X belongs in scope."
+
+   Defaults when interaction impossible:
+   - Depth: Standard
+   - Audience: Reviewer (PR) if code-related; Author otherwise
+   - Focus: Top 2 relevance clusters
+
+   Output the questions (label Q1/Q2/Q3). After answers: if ≥2 scenario classes (Alternate / Exception / Recovery / Non-Functional domain) remain unclear, you MAY ask up to TWO more targeted follow‑ups (Q4/Q5) with a one-line justification each (e.g., "Unresolved recovery path risk"). Do not exceed five total questions. Skip escalation if user explicitly declines more.
+
+3. **Understand user request**: Combine `$ARGUMENTS` + clarifying answers:
+   - Derive checklist theme (e.g., security, review, deploy, ux)
+   - Consolidate explicit must-have items mentioned by user
+   - Map focus selections to category scaffolding
+   - Infer any missing context from spec/plan/tasks (do NOT hallucinate)
+
+4. **Load feature context**: Read from FEATURE_DIR:
+   - spec.md: Feature requirements and scope
+   - plan.md (if exists): Technical details, dependencies
+   - tasks.md (if exists): Implementation tasks
+
+   **Context Loading Strategy**:
+   - Load only necessary portions relevant to active focus areas (avoid full-file dumping)
+   - Prefer summarizing long sections into concise scenario/requirement bullets
+   - Use progressive disclosure: add follow-on retrieval only if gaps detected
+   - If source docs are large, generate interim summary items instead of embedding raw text
+
+5. **Generate checklist** - Create "Unit Tests for Requirements":
+   - Create `FEATURE_DIR/checklists/` directory if it doesn't exist
+   - Generate unique checklist filename:
+     - Use short, descriptive name based on domain (e.g., `ux.md`, `api.md`, `security.md`)
+     - Format: `[domain].md`
+   - File handling behavior:
+     - If file does NOT exist: Create new file and number items starting from CHK001
+     - If file exists: Append new items to existing file, continuing from the last CHK ID (e.g., if last item is CHK015, start new items at CHK016)
+   - Never delete or replace existing checklist content - always preserve and append
+
+   **CORE PRINCIPLE - Test the Requirements, Not the Implementation**:
+   Every checklist item MUST evaluate the REQUIREMENTS THEMSELVES for:
+   - **Completeness**: Are all necessary requirements present?
+   - **Clarity**: Are requirements unambiguous and specific?
+   - **Consistency**: Do requirements align with each other?
+   - **Measurability**: Can requirements be objectively verified?
+   - **Coverage**: Are all scenarios/edge cases addressed?
+
+   **Category Structure** - Group items by requirement quality dimensions:
+   - **Requirement Completeness** (Are all necessary requirements documented?)
+   - **Requirement Clarity** (Are requirements specific and unambiguous?)
+   - **Requirement Consistency** (Do requirements align without conflicts?)
+   - **Acceptance Criteria Quality** (Are success criteria measurable?)
+   - **Scenario Coverage** (Are all flows/cases addressed?)
+   - **Edge Case Coverage** (Are boundary conditions defined?)
+   - **Non-Functional Requirements** (Performance, Security, Accessibility, etc. - are they specified?)
+   - **Dependencies & Assumptions** (Are they documented and validated?)
+   - **Ambiguities & Conflicts** (What needs clarification?)
+
+   **HOW TO WRITE CHECKLIST ITEMS - "Unit Tests for English"**:
+
+   ❌ **WRONG** (Testing implementation):
+   - "Verify landing page displays 3 episode cards"
+   - "Test hover states work on desktop"
+   - "Confirm logo click navigates home"
+
+   ✅ **CORRECT** (Testing requirements quality):
+   - "Are the exact number and layout of featured episodes specified?" [Completeness]
+   - "Is 'prominent display' quantified with specific sizing/positioning?" [Clarity]
+   - "Are hover state requirements consistent across all interactive elements?" [Consistency]
+   - "Are keyboard navigation requirements defined for all interactive UI?" [Coverage]
+   - "Is the fallback behavior specified when logo image fails to load?" [Edge Cases]
+   - "Are loading states defined for asynchronous episode data?" [Completeness]
+   - "Does the spec define visual hierarchy for competing UI elements?" [Clarity]
+
+   **ITEM STRUCTURE**:
+   Each item should follow this pattern:
+   - Question format asking about requirement quality
+   - Focus on what's WRITTEN (or not written) in the spec/plan
+   - Include quality dimension in brackets [Completeness/Clarity/Consistency/etc.]
+   - Reference spec section `[Spec §X.Y]` when checking existing requirements
+   - Use `[Gap]` marker when checking for missing requirements
+
+   **EXAMPLES BY QUALITY DIMENSION**:
+
+   Completeness:
+   - "Are error handling requirements defined for all API failure modes? [Gap]"
+   - "Are accessibility requirements specified for all interactive elements? [Completeness]"
+   - "Are mobile breakpoint requirements defined for responsive layouts? [Gap]"
+
+   Clarity:
+   - "Is 'fast loading' quantified with specific timing thresholds? [Clarity, Spec §NFR-2]"
+   - "Are 'related episodes' selection criteria explicitly defined? [Clarity, Spec §FR-5]"
+   - "Is 'prominent' defined with measurable visual properties? [Ambiguity, Spec §FR-4]"
+
+   Consistency:
+   - "Do navigation requirements align across all pages? [Consistency, Spec §FR-10]"
+   - "Are card component requirements consistent between landing and detail pages? [Consistency]"
+
+   Coverage:
+   - "Are requirements defined for zero-state scenarios (no episodes)? [Coverage, Edge Case]"
+   - "Are concurrent user interaction scenarios addressed? [Coverage, Gap]"
+   - "Are requirements specified for partial data loading failures? [Coverage, Exception Flow]"
+
+   Measurability:
+   - "Are visual hierarchy requirements measurable/testable? [Acceptance Criteria, Spec §FR-1]"
+   - "Can 'balanced visual weight' be objectively verified? [Measurability, Spec §FR-2]"
+
+   **Scenario Classification & Coverage** (Requirements Quality Focus):
+   - Check if requirements exist for: Primary, Alternate, Exception/Error, Recovery, Non-Functional scenarios
+   - For each scenario class, ask: "Are [scenario type] requirements complete, clear, and consistent?"
+   - If scenario class missing: "Are [scenario type] requirements intentionally excluded or missing? [Gap]"
+   - Include resilience/rollback when state mutation occurs: "Are rollback requirements defined for migration failures? [Gap]"
+
+   **Traceability Requirements**:
+   - MINIMUM: ≥80% of items MUST include at least one traceability reference
+   - Each item should reference: spec section `[Spec §X.Y]`, or use markers: `[Gap]`, `[Ambiguity]`, `[Conflict]`, `[Assumption]`
+   - If no ID system exists: "Is a requirement & acceptance criteria ID scheme established? [Traceability]"
+
+   **Surface & Resolve Issues** (Requirements Quality Problems):
+   Ask questions about the requirements themselves:
+   - Ambiguities: "Is the term 'fast' quantified with specific metrics? [Ambiguity, Spec §NFR-1]"
+   - Conflicts: "Do navigation requirements conflict between §FR-10 and §FR-10a? [Conflict]"
+   - Assumptions: "Is the assumption of 'always available podcast API' validated? [Assumption]"
+   - Dependencies: "Are external podcast API requirements documented? [Dependency, Gap]"
+   - Missing definitions: "Is 'visual hierarchy' defined with measurable criteria? [Gap]"
+
+   **Content Consolidation**:
+   - Soft cap: If raw candidate items > 40, prioritize by risk/impact
+   - Merge near-duplicates checking the same requirement aspect
+   - If >5 low-impact edge cases, create one item: "Are edge cases X, Y, Z addressed in requirements? [Coverage]"
+
+   **🚫 ABSOLUTELY PROHIBITED** - These make it an implementation test, not a requirements test:
+   - ❌ Any item starting with "Verify", "Test", "Confirm", "Check" + implementation behavior
+   - ❌ References to code execution, user actions, system behavior
+   - ❌ "Displays correctly", "works properly", "functions as expected"
+   - ❌ "Click", "navigate", "render", "load", "execute"
+   - ❌ Test cases, test plans, QA procedures
+   - ❌ Implementation details (frameworks, APIs, algorithms)
+
+   **✅ REQUIRED PATTERNS** - These test requirements quality:
+   - ✅ "Are [requirement type] defined/specified/documented for [scenario]?"
+   - ✅ "Is [vague term] quantified/clarified with specific criteria?"
+   - ✅ "Are requirements consistent between [section A] and [section B]?"
+   - ✅ "Can [requirement] be objectively measured/verified?"
+   - ✅ "Are [edge cases/scenarios] addressed in requirements?"
+   - ✅ "Does the spec define [missing aspect]?"
+
+6. **Structure Reference**: Generate the checklist following the canonical template in `.specify/templates/checklist-template.md` for title, meta section, category headings, and ID formatting. If template is unavailable, use: H1 title, purpose/created meta lines, `##` category sections containing `- [ ] CHK### <requirement item>` lines with globally incrementing IDs starting at CHK001.
+
+7. **Report**: Output full path to checklist file, item count, and summarize whether the run created a new file or appended to an existing one. Summarize:
+   - Focus areas selected
+   - Depth level
+   - Actor/timing
+   - Any explicit user-specified must-have items incorporated
+
+**Important**: Each `/speckit.checklist` command invocation uses a short, descriptive checklist filename and either creates a new file or appends to an existing one. This allows:
+
+- Multiple checklists of different types (e.g., `ux.md`, `test.md`, `security.md`)
+- Simple, memorable filenames that indicate checklist purpose
+- Easy identification and navigation in the `checklists/` folder
+
+To avoid clutter, use descriptive types and clean up obsolete checklists when done.
+
+## Example Checklist Types & Sample Items
+
+**UX Requirements Quality:** `ux.md`
+
+Sample items (testing the requirements, NOT the implementation):
+
+- "Are visual hierarchy requirements defined with measurable criteria? [Clarity, Spec §FR-1]"
+- "Is the number and positioning of UI elements explicitly specified? [Completeness, Spec §FR-1]"
+- "Are interaction state requirements (hover, focus, active) consistently defined? [Consistency]"
+- "Are accessibility requirements specified for all interactive elements? [Coverage, Gap]"
+- "Is fallback behavior defined when images fail to load? [Edge Case, Gap]"
+- "Can 'prominent display' be objectively measured? [Measurability, Spec §FR-4]"
+
+**API Requirements Quality:** `api.md`
+
+Sample items:
+
+- "Are error response formats specified for all failure scenarios? [Completeness]"
+- "Are rate limiting requirements quantified with specific thresholds? [Clarity]"
+- "Are authentication requirements consistent across all endpoints? [Consistency]"
+- "Are retry/timeout requirements defined for external dependencies? [Coverage, Gap]"
+- "Is versioning strategy documented in requirements? [Gap]"
+
+**Performance Requirements Quality:** `performance.md`
+
+Sample items:
+
+- "Are performance requirements quantified with specific metrics? [Clarity]"
+- "Are performance targets defined for all critical user journeys? [Coverage]"
+- "Are performance requirements under different load conditions specified? [Completeness]"
+- "Can performance requirements be objectively measured? [Measurability]"
+- "Are degradation requirements defined for high-load scenarios? [Edge Case, Gap]"
+
+**Security Requirements Quality:** `security.md`
+
+Sample items:
+
+- "Are authentication requirements specified for all protected resources? [Coverage]"
+- "Are data protection requirements defined for sensitive information? [Completeness]"
+- "Is the threat model documented and requirements aligned to it? [Traceability]"
+- "Are security requirements consistent with compliance obligations? [Consistency]"
+- "Are security failure/breach response requirements defined? [Gap, Exception Flow]"
+
+## Anti-Examples: What NOT To Do
+
+**❌ WRONG - These test implementation, not requirements:**
+
+```markdown
+- [ ] CHK001 - Verify landing page displays 3 episode cards [Spec §FR-001]
+- [ ] CHK002 - Test hover states work correctly on desktop [Spec §FR-003]
+- [ ] CHK003 - Confirm logo click navigates to home page [Spec §FR-010]
+- [ ] CHK004 - Check that related episodes section shows 3-5 items [Spec §FR-005]
+```
+
+**✅ CORRECT - These test requirements quality:**
+
+```markdown
+- [ ] CHK001 - Are the number and layout of featured episodes explicitly specified? [Completeness, Spec §FR-001]
+- [ ] CHK002 - Are hover state requirements consistently defined for all interactive elements? [Consistency, Spec §FR-003]
+- [ ] CHK003 - Are navigation requirements clear for all clickable brand elements? [Clarity, Spec §FR-010]
+- [ ] CHK004 - Is the selection criteria for related episodes documented? [Gap, Spec §FR-005]
+- [ ] CHK005 - Are loading state requirements defined for asynchronous episode data? [Gap]
+- [ ] CHK006 - Can "visual hierarchy" requirements be objectively measured? [Measurability, Spec §FR-001]
+```
+
+**Key Differences:**
+
+- Wrong: Tests if the system works correctly
+- Correct: Tests if the requirements are written correctly
+- Wrong: Verification of behavior
+- Correct: Validation of requirement quality
+- Wrong: "Does it do X?"
+- Correct: "Is X clearly specified?"

+ 186 - 0
.claude/skills/speckit-clarify/SKILL.md

@@ -0,0 +1,186 @@
+---
+name: "speckit-clarify"
+description: "Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarification questions and encoding answers back into the spec."
+argument-hint: "Optional areas to clarify in the spec"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/clarify.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Outline
+
+Goal: Detect and reduce ambiguity or missing decision points in the active feature specification and record the clarifications directly in the spec file.
+
+Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `/speckit.plan`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases.
+
+Execution steps:
+
+1. Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json -PathsOnly` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields:
+   - `FEATURE_DIR`
+   - `FEATURE_SPEC`
+   - (Optionally capture `IMPL_PLAN`, `TASKS` for future chained flows.)
+   - If JSON parsing fails, abort and instruct user to re-run `/speckit.specify` or verify feature branch environment.
+   - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).
+
+   Functional Scope & Behavior:
+   - Core user goals & success criteria
+   - Explicit out-of-scope declarations
+   - User roles / personas differentiation
+
+   Domain & Data Model:
+   - Entities, attributes, relationships
+   - Identity & uniqueness rules
+   - Lifecycle/state transitions
+   - Data volume / scale assumptions
+
+   Interaction & UX Flow:
+   - Critical user journeys / sequences
+   - Error/empty/loading states
+   - Accessibility or localization notes
+
+   Non-Functional Quality Attributes:
+   - Performance (latency, throughput targets)
+   - Scalability (horizontal/vertical, limits)
+   - Reliability & availability (uptime, recovery expectations)
+   - Observability (logging, metrics, tracing signals)
+   - Security & privacy (authN/Z, data protection, threat assumptions)
+   - Compliance / regulatory constraints (if any)
+
+   Integration & External Dependencies:
+   - External services/APIs and failure modes
+   - Data import/export formats
+   - Protocol/versioning assumptions
+
+   Edge Cases & Failure Handling:
+   - Negative scenarios
+   - Rate limiting / throttling
+   - Conflict resolution (e.g., concurrent edits)
+
+   Constraints & Tradeoffs:
+   - Technical constraints (language, storage, hosting)
+   - Explicit tradeoffs or rejected alternatives
+
+   Terminology & Consistency:
+   - Canonical glossary terms
+   - Avoided synonyms / deprecated terms
+
+   Completion Signals:
+   - Acceptance criteria testability
+   - Measurable Definition of Done style indicators
+
+   Misc / Placeholders:
+   - TODO markers / unresolved decisions
+   - Ambiguous adjectives ("robust", "intuitive") lacking quantification
+
+   For each category with Partial or Missing status, add a candidate question opportunity unless:
+   - Clarification would not materially change implementation or validation strategy
+   - Information is better deferred to planning phase (note internally)
+
+3. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
+    - Maximum of 5 total questions across the whole session.
+    - Each question must be answerable with EITHER:
+       - A short multiple‑choice selection (2–5 distinct, mutually exclusive options), OR
+       - A one-word / short‑phrase answer (explicitly constrain: "Answer in <=5 words").
+    - Only include questions whose answers materially impact architecture, data modeling, task decomposition, test design, UX behavior, operational readiness, or compliance validation.
+    - Ensure category coverage balance: attempt to cover the highest impact unresolved categories first; avoid asking two low-impact questions when a single high-impact area (e.g., security posture) is unresolved.
+    - Exclude questions already answered, trivial stylistic preferences, or plan-level execution details (unless blocking correctness).
+    - Favor clarifications that reduce downstream rework risk or prevent misaligned acceptance tests.
+    - If more than 5 categories remain unresolved, select the top 5 by (Impact * Uncertainty) heuristic.
+
+4. Sequential questioning loop (interactive):
+    - Present EXACTLY ONE question at a time.
+    - For multiple‑choice questions:
+       - **Analyze all options** and determine the **most suitable option** based on:
+          - Best practices for the project type
+          - Common patterns in similar implementations
+          - Risk reduction (security, performance, maintainability)
+          - Alignment with any explicit project goals or constraints visible in the spec
+       - Present your **recommended option prominently** at the top with clear reasoning (1-2 sentences explaining why this is the best choice).
+       - Format as: `**Recommended:** Option [X] - <reasoning>`
+       - Then render all options as a Markdown table:
+
+       | Option | Description |
+       |--------|-------------|
+       | A | <Option A description> |
+       | B | <Option B description> |
+       | C | <Option C description> (add D/E as needed up to 5) |
+       | Short | Provide a different short answer (<=5 words) (Include only if free-form alternative is appropriate) |
+
+       - After the table, add: `You can reply with the option letter (e.g., "A"), accept the recommendation by saying "yes" or "recommended", or provide your own short answer.`
+    - For short‑answer style (no meaningful discrete options):
+       - Provide your **suggested answer** based on best practices and context.
+       - Format as: `**Suggested:** <your proposed answer> - <brief reasoning>`
+       - Then output: `Format: Short answer (<=5 words). You can accept the suggestion by saying "yes" or "suggested", or provide your own answer.`
+    - After the user answers:
+       - If the user replies with "yes", "recommended", or "suggested", use your previously stated recommendation/suggestion as the answer.
+       - Otherwise, validate the answer maps to one option or fits the <=5 word constraint.
+       - If ambiguous, ask for a quick disambiguation (count still belongs to same question; do not advance).
+       - Once satisfactory, record it in working memory (do not yet write to disk) and move to the next queued question.
+    - Stop asking further questions when:
+       - All critical ambiguities resolved early (remaining queued items become unnecessary), OR
+       - User signals completion ("done", "good", "no more"), OR
+       - You reach 5 asked questions.
+    - Never reveal future queued questions in advance.
+    - If no valid questions exist at start, immediately report no critical ambiguities.
+
+5. Integration after EACH accepted answer (incremental update approach):
+    - Maintain in-memory representation of the spec (loaded once at start) plus the raw file contents.
+    - For the first integrated answer in this session:
+       - Ensure a `## Clarifications` section exists (create it just after the highest-level contextual/overview section per the spec template if missing).
+       - Under it, create (if not present) a `### Session YYYY-MM-DD` subheading for today.
+    - Append a bullet line immediately after acceptance: `- Q: <question> → A: <final answer>`.
+    - Then immediately apply the clarification to the most appropriate section(s):
+       - Functional ambiguity → Update or add a bullet in Functional Requirements.
+       - User interaction / actor distinction → Update User Stories or Actors subsection (if present) with clarified role, constraint, or scenario.
+       - Data shape / entities → Update Data Model (add fields, types, relationships) preserving ordering; note added constraints succinctly.
+       - Non-functional constraint → Add/modify measurable criteria in Success Criteria > Measurable Outcomes (convert vague adjective to metric or explicit target).
+       - Edge case / negative flow → Add a new bullet under Edge Cases / Error Handling (or create such subsection if template provides placeholder for it).
+       - Terminology conflict → Normalize term across spec; retain original only if necessary by adding `(formerly referred to as "X")` once.
+    - If the clarification invalidates an earlier ambiguous statement, replace that statement instead of duplicating; leave no obsolete contradictory text.
+    - Save the spec file AFTER each integration to minimize risk of context loss (atomic overwrite).
+    - Preserve formatting: do not reorder unrelated sections; keep heading hierarchy intact.
+    - Keep each inserted clarification minimal and testable (avoid narrative drift).
+
+6. Validation (performed after EACH write plus final pass):
+   - Clarifications session contains exactly one bullet per accepted answer (no duplicates).
+   - Total asked (accepted) questions ≤ 5.
+   - Updated sections contain no lingering vague placeholders the new answer was meant to resolve.
+   - No contradictory earlier statement remains (scan for now-invalid alternative choices removed).
+   - Markdown structure valid; only allowed new headings: `## Clarifications`, `### Session YYYY-MM-DD`.
+   - Terminology consistency: same canonical term used across all updated sections.
+
+7. Write the updated spec back to `FEATURE_SPEC`.
+
+8. Report completion (after questioning loop ends or early termination):
+   - Number of questions asked & answered.
+   - Path to updated spec.
+   - Sections touched (list names).
+   - Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota or better suited for planning), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
+   - If any Outstanding or Deferred remain, recommend whether to proceed to `/speckit.plan` or run `/speckit.clarify` again later post-plan.
+   - Suggested next command.
+
+Behavior rules:
+
+- If no meaningful ambiguities found (or all potential questions would be low-impact), respond: "No critical ambiguities detected worth formal clarification." and suggest proceeding.
+- If spec file missing, instruct user to run `/speckit.specify` first (do not create a new spec here).
+- Never exceed 5 total asked questions (clarification retries for a single question do not count as new questions).
+- Avoid speculative tech stack questions unless the absence blocks functional clarity.
+- Respect user early termination signals ("stop", "done", "proceed").
+- If no questions asked due to full coverage, output a compact coverage summary (all categories Clear) then suggest advancing.
+- If quota reached with unresolved high-impact categories remaining, explicitly flag them under Deferred with rationale.
+
+Context for prioritization: $ARGUMENTS

+ 89 - 0
.claude/skills/speckit-constitution/SKILL.md

@@ -0,0 +1,89 @@
+---
+name: "speckit-constitution"
+description: "Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync."
+argument-hint: "Principles or values for the project constitution"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/constitution.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Outline
+
+You are updating the project constitution at `.specify/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.
+
+**Note**: If `.specify/memory/constitution.md` does not exist yet, it should have been initialized from `.specify/templates/constitution-template.md` during project setup. If it's missing, copy the template first.
+
+Follow this execution flow:
+
+1. Load the existing constitution at `.specify/memory/constitution.md`.
+   - Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
+   **IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.
+
+2. Collect/derive values for placeholders:
+   - If user input (conversation) supplies a value, use it.
+   - Otherwise infer from existing repo context (README, docs, prior constitution versions if embedded).
+   - For governance dates: `RATIFICATION_DATE` is the original adoption date (if unknown ask or mark TODO), `LAST_AMENDED_DATE` is today if changes are made, otherwise keep previous.
+   - `CONSTITUTION_VERSION` must increment according to semantic versioning rules:
+     - MAJOR: Backward incompatible governance/principle removals or redefinitions.
+     - MINOR: New principle/section added or materially expanded guidance.
+     - PATCH: Clarifications, wording, typo fixes, non-semantic refinements.
+   - If version bump type ambiguous, propose reasoning before finalizing.
+
+3. Draft the updated constitution content:
+   - Replace every placeholder with concrete text (no bracketed tokens left except intentionally retained template slots that the project has chosen not to define yet—explicitly justify any left).
+   - Preserve heading hierarchy and comments can be removed once replaced unless they still add clarifying guidance.
+   - Ensure each Principle section: succinct name line, paragraph (or bullet list) capturing non‑negotiable rules, explicit rationale if not obvious.
+   - Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.
+
+4. Consistency propagation checklist (convert prior checklist into active validations):
+   - Read `.specify/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
+   - Read `.specify/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
+   - Read `.specify/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
+   - Read each command file in `.specify/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
+   - Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.
+
+5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
+   - Version change: old → new
+   - List of modified principles (old title → new title if renamed)
+   - Added sections
+   - Removed sections
+   - Templates requiring updates (✅ updated / ⚠ pending) with file paths
+   - Follow-up TODOs if any placeholders intentionally deferred.
+
+6. Validation before final output:
+   - No remaining unexplained bracket tokens.
+   - Version line matches report.
+   - Dates ISO format YYYY-MM-DD.
+   - Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).
+
+7. Write the completed constitution back to `.specify/memory/constitution.md` (overwrite).
+
+8. Output a final summary to the user with:
+   - New version and bump rationale.
+   - Any files flagged for manual follow-up.
+   - Suggested commit message (e.g., `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).
+
+Formatting & Style Requirements:
+
+- Use Markdown headings exactly as in the template (do not demote/promote levels).
+- Wrap long rationale lines to keep readability (<100 chars ideally) but do not hard enforce with awkward breaks.
+- Keep a single blank line between sections.
+- Avoid trailing whitespace.
+
+If the user supplies partial updates (e.g., only one principle revision), still perform validation and version decision steps.
+
+If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.
+
+Do not create a new template; always operate on the existing `.specify/memory/constitution.md` file.

+ 207 - 0
.claude/skills/speckit-implement/SKILL.md

@@ -0,0 +1,207 @@
+---
+name: "speckit-implement"
+description: "Execute the implementation plan by processing and executing all tasks defined in tasks.md"
+argument-hint: "Optional implementation guidance or task filter"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/implement.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Pre-Execution Checks
+
+**Check for extension hooks (before implementation)**:
+- Check if `.specify/extensions.yml` exists in the project root.
+- If it exists, read it and look for entries under the `hooks.before_implement` key
+- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+  - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+  - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+- For each executable hook, output the following based on its `optional` flag:
+  - **Optional hook** (`optional: true`):
+    ```
+    ## Extension Hooks
+
+    **Optional Pre-Hook**: {extension}
+    Command: `/{command}`
+    Description: {description}
+
+    Prompt: {prompt}
+    To execute: `/{command}`
+    ```
+  - **Mandatory hook** (`optional: false`):
+    ```
+    ## Extension Hooks
+
+    **Automatic Pre-Hook**: {extension}
+    Executing: `/{command}`
+    EXECUTE_COMMAND: {command}
+    
+    Wait for the result of the hook command before proceeding to the Outline.
+    ```
+- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+## Outline
+
+1. Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+2. **Check checklists status** (if FEATURE_DIR/checklists/ exists):
+   - Scan all checklist files in the checklists/ directory
+   - For each checklist, count:
+     - Total items: All lines matching `- [ ]` or `- [X]` or `- [x]`
+     - Completed items: Lines matching `- [X]` or `- [x]`
+     - Incomplete items: Lines matching `- [ ]`
+   - Create a status table:
+
+     ```text
+     | Checklist | Total | Completed | Incomplete | Status |
+     |-----------|-------|-----------|------------|--------|
+     | ux.md     | 12    | 12        | 0          | ✓ PASS |
+     | test.md   | 8     | 5         | 3          | ✗ FAIL |
+     | security.md | 6   | 6         | 0          | ✓ PASS |
+     ```
+
+   - Calculate overall status:
+     - **PASS**: All checklists have 0 incomplete items
+     - **FAIL**: One or more checklists have incomplete items
+
+   - **If any checklist is incomplete**:
+     - Display the table with incomplete item counts
+     - **STOP** and ask: "Some checklists are incomplete. Do you want to proceed with implementation anyway? (yes/no)"
+     - Wait for user response before continuing
+     - If user says "no" or "wait" or "stop", halt execution
+     - If user says "yes" or "proceed" or "continue", proceed to step 3
+
+   - **If all checklists are complete**:
+     - Display the table showing all checklists passed
+     - Automatically proceed to step 3
+
+3. Load and analyze the implementation context:
+   - **REQUIRED**: Read tasks.md for the complete task list and execution plan
+   - **REQUIRED**: Read plan.md for tech stack, architecture, and file structure
+   - **IF EXISTS**: Read data-model.md for entities and relationships
+   - **IF EXISTS**: Read contracts/ for API specifications and test requirements
+   - **IF EXISTS**: Read research.md for technical decisions and constraints
+   - **IF EXISTS**: Read quickstart.md for integration scenarios
+
+4. **Project Setup Verification**:
+   - **REQUIRED**: Create/verify ignore files based on actual project setup:
+
+   **Detection & Creation Logic**:
+   - Check if the following command succeeds to determine if the repository is a git repo (create/verify .gitignore if so):
+
+     ```sh
+     git rev-parse --git-dir 2>/dev/null
+     ```
+
+   - Check if Dockerfile* exists or Docker in plan.md → create/verify .dockerignore
+   - Check if .eslintrc* exists → create/verify .eslintignore
+   - Check if eslint.config.* exists → ensure the config's `ignores` entries cover required patterns
+   - Check if .prettierrc* exists → create/verify .prettierignore
+   - Check if .npmrc or package.json exists → create/verify .npmignore (if publishing)
+   - Check if terraform files (*.tf) exist → create/verify .terraformignore
+   - Check if .helmignore needed (helm charts present) → create/verify .helmignore
+
+   **If ignore file already exists**: Verify it contains essential patterns, append missing critical patterns only
+   **If ignore file missing**: Create with full pattern set for detected technology
+
+   **Common Patterns by Technology** (from plan.md tech stack):
+   - **Node.js/JavaScript/TypeScript**: `node_modules/`, `dist/`, `build/`, `*.log`, `.env*`
+   - **Python**: `__pycache__/`, `*.pyc`, `.venv/`, `venv/`, `dist/`, `*.egg-info/`
+   - **Java**: `target/`, `*.class`, `*.jar`, `.gradle/`, `build/`
+   - **C#/.NET**: `bin/`, `obj/`, `*.user`, `*.suo`, `packages/`
+   - **Go**: `*.exe`, `*.test`, `vendor/`, `*.out`
+   - **Ruby**: `.bundle/`, `log/`, `tmp/`, `*.gem`, `vendor/bundle/`
+   - **PHP**: `vendor/`, `*.log`, `*.cache`, `*.env`
+   - **Rust**: `target/`, `debug/`, `release/`, `*.rs.bk`, `*.rlib`, `*.prof*`, `.idea/`, `*.log`, `.env*`
+   - **Kotlin**: `build/`, `out/`, `.gradle/`, `.idea/`, `*.class`, `*.jar`, `*.iml`, `*.log`, `.env*`
+   - **C++**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.so`, `*.a`, `*.exe`, `*.dll`, `.idea/`, `*.log`, `.env*`
+   - **C**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.a`, `*.so`, `*.exe`, `*.dll`, `autom4te.cache/`, `config.status`, `config.log`, `.idea/`, `*.log`, `.env*`
+   - **Swift**: `.build/`, `DerivedData/`, `*.swiftpm/`, `Packages/`
+   - **R**: `.Rproj.user/`, `.Rhistory`, `.RData`, `.Ruserdata`, `*.Rproj`, `packrat/`, `renv/`
+   - **Universal**: `.DS_Store`, `Thumbs.db`, `*.tmp`, `*.swp`, `.vscode/`, `.idea/`
+
+   **Tool-Specific Patterns**:
+   - **Docker**: `node_modules/`, `.git/`, `Dockerfile*`, `.dockerignore`, `*.log*`, `.env*`, `coverage/`
+   - **ESLint**: `node_modules/`, `dist/`, `build/`, `coverage/`, `*.min.js`
+   - **Prettier**: `node_modules/`, `dist/`, `build/`, `coverage/`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
+   - **Terraform**: `.terraform/`, `*.tfstate*`, `*.tfvars`, `.terraform.lock.hcl`
+   - **Kubernetes/k8s**: `*.secret.yaml`, `secrets/`, `.kube/`, `kubeconfig*`, `*.key`, `*.crt`
+
+5. Parse tasks.md structure and extract:
+   - **Task phases**: Setup, Tests, Core, Integration, Polish
+   - **Task dependencies**: Sequential vs parallel execution rules
+   - **Task details**: ID, description, file paths, parallel markers [P]
+   - **Execution flow**: Order and dependency requirements
+
+6. Execute implementation following the task plan:
+   - **Phase-by-phase execution**: Complete each phase before moving to the next
+   - **Respect dependencies**: Run sequential tasks in order, parallel tasks [P] can run together  
+   - **Follow TDD approach**: Execute test tasks before their corresponding implementation tasks
+   - **File-based coordination**: Tasks affecting the same files must run sequentially
+   - **Validation checkpoints**: Verify each phase completion before proceeding
+
+7. Implementation execution rules:
+   - **Setup first**: Initialize project structure, dependencies, configuration
+   - **Tests before code**: If you need to write tests for contracts, entities, and integration scenarios
+   - **Core development**: Implement models, services, CLI commands, endpoints
+   - **Integration work**: Database connections, middleware, logging, external services
+   - **Polish and validation**: Unit tests, performance optimization, documentation
+
+8. Progress tracking and error handling:
+   - Report progress after each completed task
+   - Halt execution if any non-parallel task fails
+   - For parallel tasks [P], continue with successful tasks, report failed ones
+   - Provide clear error messages with context for debugging
+   - Suggest next steps if implementation cannot proceed
+   - **IMPORTANT** For completed tasks, make sure to mark the task off as [X] in the tasks file.
+
+9. Completion validation:
+   - Verify all required tasks are completed
+   - Check that implemented features match the original specification
+   - Validate that tests pass and coverage meets requirements
+   - Confirm the implementation follows the technical plan
+   - Report final status with summary of completed work
+
+Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/speckit.tasks` first to regenerate the task list.
+
+10. **Check for extension hooks**: After completion validation, check if `.specify/extensions.yml` exists in the project root.
+    - If it exists, read it and look for entries under the `hooks.after_implement` key
+    - If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+    - Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+    - For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+      - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+      - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+    - For each executable hook, output the following based on its `optional` flag:
+      - **Optional hook** (`optional: true`):
+        ```
+        ## Extension Hooks
+
+        **Optional Hook**: {extension}
+        Command: `/{command}`
+        Description: {description}
+
+        Prompt: {prompt}
+        To execute: `/{command}`
+        ```
+      - **Mandatory hook** (`optional: false`):
+        ```
+        ## Extension Hooks
+
+        **Automatic Hook**: {extension}
+        Executing: `/{command}`
+        EXECUTE_COMMAND: {command}
+        ```
+    - If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently

+ 154 - 0
.claude/skills/speckit-plan/SKILL.md

@@ -0,0 +1,154 @@
+---
+name: "speckit-plan"
+description: "Execute the implementation planning workflow using the plan template to generate design artifacts."
+argument-hint: "Optional guidance for the planning phase"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/plan.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Pre-Execution Checks
+
+**Check for extension hooks (before planning)**:
+- Check if `.specify/extensions.yml` exists in the project root.
+- If it exists, read it and look for entries under the `hooks.before_plan` key
+- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+  - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+  - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+- For each executable hook, output the following based on its `optional` flag:
+  - **Optional hook** (`optional: true`):
+    ```
+    ## Extension Hooks
+
+    **Optional Pre-Hook**: {extension}
+    Command: `/{command}`
+    Description: {description}
+
+    Prompt: {prompt}
+    To execute: `/{command}`
+    ```
+  - **Mandatory hook** (`optional: false`):
+    ```
+    ## Extension Hooks
+
+    **Automatic Pre-Hook**: {extension}
+    Executing: `/{command}`
+    EXECUTE_COMMAND: {command}
+
+    Wait for the result of the hook command before proceeding to the Outline.
+    ```
+- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+## Outline
+
+1. **Setup**: Run `.specify/scripts/powershell/setup-plan.ps1 -Json` from repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+2. **Load context**: Read FEATURE_SPEC and `.specify/memory/constitution.md`. Load IMPL_PLAN template (already copied).
+
+3. **Execute plan workflow**: Follow the structure in IMPL_PLAN template to:
+   - Fill Technical Context (mark unknowns as "NEEDS CLARIFICATION")
+   - Fill Constitution Check section from constitution
+   - Evaluate gates (ERROR if violations unjustified)
+   - Phase 0: Generate research.md (resolve all NEEDS CLARIFICATION)
+   - Phase 1: Generate data-model.md, contracts/, quickstart.md
+   - Phase 1: Update agent context by running the agent script
+   - Re-evaluate Constitution Check post-design
+
+4. **Stop and report**: Command ends after Phase 2 planning. Report branch, IMPL_PLAN path, and generated artifacts.
+
+5. **Check for extension hooks**: After reporting, check if `.specify/extensions.yml` exists in the project root.
+   - If it exists, read it and look for entries under the `hooks.after_plan` key
+   - If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+   - Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+   - For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+     - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+     - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+   - For each executable hook, output the following based on its `optional` flag:
+     - **Optional hook** (`optional: true`):
+       ```
+       ## Extension Hooks
+
+       **Optional Hook**: {extension}
+       Command: `/{command}`
+       Description: {description}
+
+       Prompt: {prompt}
+       To execute: `/{command}`
+       ```
+     - **Mandatory hook** (`optional: false`):
+       ```
+       ## Extension Hooks
+
+       **Automatic Hook**: {extension}
+       Executing: `/{command}`
+       EXECUTE_COMMAND: {command}
+       ```
+   - If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+## Phases
+
+### Phase 0: Outline & Research
+
+1. **Extract unknowns from Technical Context** above:
+   - For each NEEDS CLARIFICATION → research task
+   - For each dependency → best practices task
+   - For each integration → patterns task
+
+2. **Generate and dispatch research agents**:
+
+   ```text
+   For each unknown in Technical Context:
+     Task: "Research {unknown} for {feature context}"
+   For each technology choice:
+     Task: "Find best practices for {tech} in {domain}"
+   ```
+
+3. **Consolidate findings** in `research.md` using format:
+   - Decision: [what was chosen]
+   - Rationale: [why chosen]
+   - Alternatives considered: [what else evaluated]
+
+**Output**: research.md with all NEEDS CLARIFICATION resolved
+
+### Phase 1: Design & Contracts
+
+**Prerequisites:** `research.md` complete
+
+1. **Extract entities from feature spec** → `data-model.md`:
+   - Entity name, fields, relationships
+   - Validation rules from requirements
+   - State transitions if applicable
+
+2. **Define interface contracts** (if project has external interfaces) → `/contracts/`:
+   - Identify what interfaces the project exposes to users or other systems
+   - Document the contract format appropriate for the project type
+   - Examples: public APIs for libraries, command schemas for CLI tools, endpoints for web services, grammars for parsers, UI contracts for applications
+   - Skip if project is purely internal (build scripts, one-off tools, etc.)
+
+3. **Agent context update**:
+   - Run `.specify/scripts/powershell/update-agent-context.ps1 -AgentType claude`
+   - These scripts detect which AI agent is in use
+   - Update the appropriate agent-specific context file
+   - Add only new technology from current plan
+   - Preserve manual additions between markers
+
+**Output**: data-model.md, /contracts/*, quickstart.md, agent-specific file
+
+## Key rules
+
+- Use absolute paths
+- ERROR on gate failures or unresolved clarifications

+ 307 - 0
.claude/skills/speckit-specify/SKILL.md

@@ -0,0 +1,307 @@
+---
+name: "speckit-specify"
+description: "Create or update the feature specification from a natural language feature description."
+argument-hint: "Describe the feature you want to specify"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/specify.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Pre-Execution Checks
+
+**Check for extension hooks (before specification)**:
+- Check if `.specify/extensions.yml` exists in the project root.
+- If it exists, read it and look for entries under the `hooks.before_specify` key
+- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+  - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+  - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+- For each executable hook, output the following based on its `optional` flag:
+  - **Optional hook** (`optional: true`):
+    ```
+    ## Extension Hooks
+
+    **Optional Pre-Hook**: {extension}
+    Command: `/{command}`
+    Description: {description}
+
+    Prompt: {prompt}
+    To execute: `/{command}`
+    ```
+  - **Mandatory hook** (`optional: false`):
+    ```
+    ## Extension Hooks
+
+    **Automatic Pre-Hook**: {extension}
+    Executing: `/{command}`
+    EXECUTE_COMMAND: {command}
+
+    Wait for the result of the hook command before proceeding to the Outline.
+    ```
+- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+## Outline
+
+The text the user typed after `/speckit.specify` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `$ARGUMENTS` appears literally below. Do not ask the user to repeat it unless they provided an empty command.
+
+Given that feature description, do this:
+
+1. **Generate a concise short name** (2-4 words) for the branch:
+   - Analyze the feature description and extract the most meaningful keywords
+   - Create a 2-4 word short name that captures the essence of the feature
+   - Use action-noun format when possible (e.g., "add-user-auth", "fix-payment-bug")
+   - Preserve technical terms and acronyms (OAuth2, API, JWT, etc.)
+   - Keep it concise but descriptive enough to understand the feature at a glance
+   - Examples:
+     - "I want to add user authentication" → "user-auth"
+     - "Implement OAuth2 integration for the API" → "oauth2-api-integration"
+     - "Create a dashboard for analytics" → "analytics-dashboard"
+     - "Fix payment processing timeout bug" → "fix-payment-timeout"
+
+2. **Create the feature branch** by running the script with `--short-name` (and `--json`). In sequential mode, do NOT pass `--number` — the script auto-detects the next available number. In timestamp mode, the script generates a `YYYYMMDD-HHMMSS` prefix automatically:
+
+   **Branch numbering mode**: Before running the script, check if `.specify/init-options.json` exists and read the `branch_numbering` value.
+   - If `"timestamp"`, add `--timestamp` (Bash) or `-Timestamp` (PowerShell) to the script invocation
+   - If `"sequential"` or absent, do not add any extra flag (default behavior)
+
+   - Bash example: `.specify/scripts/powershell/create-new-feature.ps1 "$ARGUMENTS" --json --short-name "user-auth" "Add user authentication"`
+   - Bash (timestamp): `.specify/scripts/powershell/create-new-feature.ps1 "$ARGUMENTS" --json --timestamp --short-name "user-auth" "Add user authentication"`
+   - PowerShell example: `.specify/scripts/powershell/create-new-feature.ps1 "$ARGUMENTS" -Json -ShortName "user-auth" "Add user authentication"`
+   - PowerShell (timestamp): `.specify/scripts/powershell/create-new-feature.ps1 "$ARGUMENTS" -Json -Timestamp -ShortName "user-auth" "Add user authentication"`
+
+   **IMPORTANT**:
+   - Do NOT pass `--number` — the script determines the correct next number automatically
+   - Always include the JSON flag (`--json` for Bash, `-Json` for PowerShell) so the output can be parsed reliably
+   - You must only ever run this script once per feature
+   - The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for
+   - The JSON output will contain BRANCH_NAME and SPEC_FILE paths
+   - For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot")
+
+3. Load `.specify/templates/spec-template.md` to understand required sections.
+
+4. Follow this execution flow:
+
+    1. Parse user description from Input
+       If empty: ERROR "No feature description provided"
+    2. Extract key concepts from description
+       Identify: actors, actions, data, constraints
+    3. For unclear aspects:
+       - Make informed guesses based on context and industry standards
+       - Only mark with [NEEDS CLARIFICATION: specific question] if:
+         - The choice significantly impacts feature scope or user experience
+         - Multiple reasonable interpretations exist with different implications
+         - No reasonable default exists
+       - **LIMIT: Maximum 3 [NEEDS CLARIFICATION] markers total**
+       - Prioritize clarifications by impact: scope > security/privacy > user experience > technical details
+    4. Fill User Scenarios & Testing section
+       If no clear user flow: ERROR "Cannot determine user scenarios"
+    5. Generate Functional Requirements
+       Each requirement must be testable
+       Use reasonable defaults for unspecified details (document assumptions in Assumptions section)
+    6. Define Success Criteria
+       Create measurable, technology-agnostic outcomes
+       Include both quantitative metrics (time, performance, volume) and qualitative measures (user satisfaction, task completion)
+       Each criterion must be verifiable without implementation details
+    7. Identify Key Entities (if data involved)
+    8. Return: SUCCESS (spec ready for planning)
+
+5. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
+
+6. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
+
+   a. **Create Spec Quality Checklist**: Generate a checklist file at `FEATURE_DIR/checklists/requirements.md` using the checklist template structure with these validation items:
+
+      ```markdown
+      # Specification Quality Checklist: [FEATURE NAME]
+      
+      **Purpose**: Validate specification completeness and quality before proceeding to planning
+      **Created**: [DATE]
+      **Feature**: [Link to spec.md]
+      
+      ## Content Quality
+      
+      - [ ] No implementation details (languages, frameworks, APIs)
+      - [ ] Focused on user value and business needs
+      - [ ] Written for non-technical stakeholders
+      - [ ] All mandatory sections completed
+      
+      ## Requirement Completeness
+      
+      - [ ] No [NEEDS CLARIFICATION] markers remain
+      - [ ] Requirements are testable and unambiguous
+      - [ ] Success criteria are measurable
+      - [ ] Success criteria are technology-agnostic (no implementation details)
+      - [ ] All acceptance scenarios are defined
+      - [ ] Edge cases are identified
+      - [ ] Scope is clearly bounded
+      - [ ] Dependencies and assumptions identified
+      
+      ## Feature Readiness
+      
+      - [ ] All functional requirements have clear acceptance criteria
+      - [ ] User scenarios cover primary flows
+      - [ ] Feature meets measurable outcomes defined in Success Criteria
+      - [ ] No implementation details leak into specification
+      
+      ## Notes
+      
+      - Items marked incomplete require spec updates before `/speckit.clarify` or `/speckit.plan`
+      ```
+
+   b. **Run Validation Check**: Review the spec against each checklist item:
+      - For each item, determine if it passes or fails
+      - Document specific issues found (quote relevant spec sections)
+
+   c. **Handle Validation Results**:
+
+      - **If all items pass**: Mark checklist complete and proceed to step 7
+
+      - **If items fail (excluding [NEEDS CLARIFICATION])**:
+        1. List the failing items and specific issues
+        2. Update the spec to address each issue
+        3. Re-run validation until all items pass (max 3 iterations)
+        4. If still failing after 3 iterations, document remaining issues in checklist notes and warn user
+
+      - **If [NEEDS CLARIFICATION] markers remain**:
+        1. Extract all [NEEDS CLARIFICATION: ...] markers from the spec
+        2. **LIMIT CHECK**: If more than 3 markers exist, keep only the 3 most critical (by scope/security/UX impact) and make informed guesses for the rest
+        3. For each clarification needed (max 3), present options to user in this format:
+
+           ```markdown
+           ## Question [N]: [Topic]
+           
+           **Context**: [Quote relevant spec section]
+           
+           **What we need to know**: [Specific question from NEEDS CLARIFICATION marker]
+           
+           **Suggested Answers**:
+           
+           | Option | Answer | Implications |
+           |--------|--------|--------------|
+           | A      | [First suggested answer] | [What this means for the feature] |
+           | B      | [Second suggested answer] | [What this means for the feature] |
+           | C      | [Third suggested answer] | [What this means for the feature] |
+           | Custom | Provide your own answer | [Explain how to provide custom input] |
+           
+           **Your choice**: _[Wait for user response]_
+           ```
+
+        4. **CRITICAL - Table Formatting**: Ensure markdown tables are properly formatted:
+           - Use consistent spacing with pipes aligned
+           - Each cell should have spaces around content: `| Content |` not `|Content|`
+           - Header separator must have at least 3 dashes: `|--------|`
+           - Test that the table renders correctly in markdown preview
+        5. Number questions sequentially (Q1, Q2, Q3 - max 3 total)
+        6. Present all questions together before waiting for responses
+        7. Wait for user to respond with their choices for all questions (e.g., "Q1: A, Q2: Custom - [details], Q3: B")
+        8. Update the spec by replacing each [NEEDS CLARIFICATION] marker with the user's selected or provided answer
+        9. Re-run validation after all clarifications are resolved
+
+   d. **Update Checklist**: After each validation iteration, update the checklist file with current pass/fail status
+
+7. Report completion with branch name, spec file path, checklist results, and readiness for the next phase (`/speckit.clarify` or `/speckit.plan`).
+
+8. **Check for extension hooks**: After reporting completion, check if `.specify/extensions.yml` exists in the project root.
+   - If it exists, read it and look for entries under the `hooks.after_specify` key
+   - If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+   - Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+   - For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+     - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+     - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+   - For each executable hook, output the following based on its `optional` flag:
+     - **Optional hook** (`optional: true`):
+       ```
+       ## Extension Hooks
+
+       **Optional Hook**: {extension}
+       Command: `/{command}`
+       Description: {description}
+
+       Prompt: {prompt}
+       To execute: `/{command}`
+       ```
+     - **Mandatory hook** (`optional: false`):
+       ```
+       ## Extension Hooks
+
+       **Automatic Hook**: {extension}
+       Executing: `/{command}`
+       EXECUTE_COMMAND: {command}
+       ```
+   - If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+**NOTE:** The script creates and checks out the new branch and initializes the spec file before writing.
+
+## Quick Guidelines
+
+- Focus on **WHAT** users need and **WHY**.
+- Avoid HOW to implement (no tech stack, APIs, code structure).
+- Written for business stakeholders, not developers.
+- DO NOT create any checklists that are embedded in the spec. That will be a separate command.
+
+### Section Requirements
+
+- **Mandatory sections**: Must be completed for every feature
+- **Optional sections**: Include only when relevant to the feature
+- When a section doesn't apply, remove it entirely (don't leave as "N/A")
+
+### For AI Generation
+
+When creating this spec from a user prompt:
+
+1. **Make informed guesses**: Use context, industry standards, and common patterns to fill gaps
+2. **Document assumptions**: Record reasonable defaults in the Assumptions section
+3. **Limit clarifications**: Maximum 3 [NEEDS CLARIFICATION] markers - use only for critical decisions that:
+   - Significantly impact feature scope or user experience
+   - Have multiple reasonable interpretations with different implications
+   - Lack any reasonable default
+4. **Prioritize clarifications**: scope > security/privacy > user experience > technical details
+5. **Think like a tester**: Every vague requirement should fail the "testable and unambiguous" checklist item
+6. **Common areas needing clarification** (only if no reasonable default exists):
+   - Feature scope and boundaries (include/exclude specific use cases)
+   - User types and permissions (if multiple conflicting interpretations possible)
+   - Security/compliance requirements (when legally/financially significant)
+
+**Examples of reasonable defaults** (don't ask about these):
+
+- Data retention: Industry-standard practices for the domain
+- Performance targets: Standard web/mobile app expectations unless specified
+- Error handling: User-friendly messages with appropriate fallbacks
+- Authentication method: Standard session-based or OAuth2 for web apps
+- Integration patterns: Use project-appropriate patterns (REST/GraphQL for web services, function calls for libraries, CLI args for tools, etc.)
+
+### Success Criteria Guidelines
+
+Success criteria must be:
+
+1. **Measurable**: Include specific metrics (time, percentage, count, rate)
+2. **Technology-agnostic**: No mention of frameworks, languages, databases, or tools
+3. **User-focused**: Describe outcomes from user/business perspective, not system internals
+4. **Verifiable**: Can be tested/validated without knowing implementation details
+
+**Good examples**:
+
+- "Users can complete checkout in under 3 minutes"
+- "System supports 10,000 concurrent users"
+- "95% of searches return results in under 1 second"
+- "Task completion rate improves by 40%"
+
+**Bad examples** (implementation-focused):
+
+- "API response time is under 200ms" (too technical, use "Users see results instantly")
+- "Database can handle 1000 TPS" (implementation detail, use user-facing metric)
+- "React components render efficiently" (framework-specific)
+- "Redis cache hit rate above 80%" (technology-specific)

+ 200 - 0
.claude/skills/speckit-tasks/SKILL.md

@@ -0,0 +1,200 @@
+---
+name: "speckit-tasks"
+description: "Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts."
+argument-hint: "Optional task generation constraints"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/tasks.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Pre-Execution Checks
+
+**Check for extension hooks (before tasks generation)**:
+- Check if `.specify/extensions.yml` exists in the project root.
+- If it exists, read it and look for entries under the `hooks.before_tasks` key
+- If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+- Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+- For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+  - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+  - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+- For each executable hook, output the following based on its `optional` flag:
+  - **Optional hook** (`optional: true`):
+    ```
+    ## Extension Hooks
+
+    **Optional Pre-Hook**: {extension}
+    Command: `/{command}`
+    Description: {description}
+
+    Prompt: {prompt}
+    To execute: `/{command}`
+    ```
+  - **Mandatory hook** (`optional: false`):
+    ```
+    ## Extension Hooks
+
+    **Automatic Pre-Hook**: {extension}
+    Executing: `/{command}`
+    EXECUTE_COMMAND: {command}
+    
+    Wait for the result of the hook command before proceeding to the Outline.
+    ```
+- If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+## Outline
+
+1. **Setup**: Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+
+2. **Load design documents**: Read from FEATURE_DIR:
+   - **Required**: plan.md (tech stack, libraries, structure), spec.md (user stories with priorities)
+   - **Optional**: data-model.md (entities), contracts/ (interface contracts), research.md (decisions), quickstart.md (test scenarios)
+   - Note: Not all projects have all documents. Generate tasks based on what's available.
+
+3. **Execute task generation workflow**:
+   - Load plan.md and extract tech stack, libraries, project structure
+   - Load spec.md and extract user stories with their priorities (P1, P2, P3, etc.)
+   - If data-model.md exists: Extract entities and map to user stories
+   - If contracts/ exists: Map interface contracts to user stories
+   - If research.md exists: Extract decisions for setup tasks
+   - Generate tasks organized by user story (see Task Generation Rules below)
+   - Generate dependency graph showing user story completion order
+   - Create parallel execution examples per user story
+   - Validate task completeness (each user story has all needed tasks, independently testable)
+
+4. **Generate tasks.md**: Use `.specify/templates/tasks-template.md` as structure, fill with:
+   - Correct feature name from plan.md
+   - Phase 1: Setup tasks (project initialization)
+   - Phase 2: Foundational tasks (blocking prerequisites for all user stories)
+   - Phase 3+: One phase per user story (in priority order from spec.md)
+   - Each phase includes: story goal, independent test criteria, tests (if requested), implementation tasks
+   - Final Phase: Polish & cross-cutting concerns
+   - All tasks must follow the strict checklist format (see Task Generation Rules below)
+   - Clear file paths for each task
+   - Dependencies section showing story completion order
+   - Parallel execution examples per story
+   - Implementation strategy section (MVP first, incremental delivery)
+
+5. **Report**: Output path to generated tasks.md and summary:
+   - Total task count
+   - Task count per user story
+   - Parallel opportunities identified
+   - Independent test criteria for each story
+   - Suggested MVP scope (typically just User Story 1)
+   - Format validation: Confirm ALL tasks follow the checklist format (checkbox, ID, labels, file paths)
+
+6. **Check for extension hooks**: After tasks.md is generated, check if `.specify/extensions.yml` exists in the project root.
+   - If it exists, read it and look for entries under the `hooks.after_tasks` key
+   - If the YAML cannot be parsed or is invalid, skip hook checking silently and continue normally
+   - Filter out hooks where `enabled` is explicitly `false`. Treat hooks without an `enabled` field as enabled by default.
+   - For each remaining hook, do **not** attempt to interpret or evaluate hook `condition` expressions:
+     - If the hook has no `condition` field, or it is null/empty, treat the hook as executable
+     - If the hook defines a non-empty `condition`, skip the hook and leave condition evaluation to the HookExecutor implementation
+   - For each executable hook, output the following based on its `optional` flag:
+     - **Optional hook** (`optional: true`):
+       ```
+       ## Extension Hooks
+
+       **Optional Hook**: {extension}
+       Command: `/{command}`
+       Description: {description}
+
+       Prompt: {prompt}
+       To execute: `/{command}`
+       ```
+     - **Mandatory hook** (`optional: false`):
+       ```
+       ## Extension Hooks
+
+       **Automatic Hook**: {extension}
+       Executing: `/{command}`
+       EXECUTE_COMMAND: {command}
+       ```
+   - If no hooks are registered or `.specify/extensions.yml` does not exist, skip silently
+
+Context for task generation: $ARGUMENTS
+
+The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context.
+
+## Task Generation Rules
+
+**CRITICAL**: Tasks MUST be organized by user story to enable independent implementation and testing.
+
+**Tests are OPTIONAL**: Only generate test tasks if explicitly requested in the feature specification or if user requests TDD approach.
+
+### Checklist Format (REQUIRED)
+
+Every task MUST strictly follow this format:
+
+```text
+- [ ] [TaskID] [P?] [Story?] Description with file path
+```
+
+**Format Components**:
+
+1. **Checkbox**: ALWAYS start with `- [ ]` (markdown checkbox)
+2. **Task ID**: Sequential number (T001, T002, T003...) in execution order
+3. **[P] marker**: Include ONLY if task is parallelizable (different files, no dependencies on incomplete tasks)
+4. **[Story] label**: REQUIRED for user story phase tasks only
+   - Format: [US1], [US2], [US3], etc. (maps to user stories from spec.md)
+   - Setup phase: NO story label
+   - Foundational phase: NO story label  
+   - User Story phases: MUST have story label
+   - Polish phase: NO story label
+5. **Description**: Clear action with exact file path
+
+**Examples**:
+
+- ✅ CORRECT: `- [ ] T001 Create project structure per implementation plan`
+- ✅ CORRECT: `- [ ] T005 [P] Implement authentication middleware in src/middleware/auth.py`
+- ✅ CORRECT: `- [ ] T012 [P] [US1] Create User model in src/models/user.py`
+- ✅ CORRECT: `- [ ] T014 [US1] Implement UserService in src/services/user_service.py`
+- ❌ WRONG: `- [ ] Create User model` (missing ID and Story label)
+- ❌ WRONG: `T001 [US1] Create model` (missing checkbox)
+- ❌ WRONG: `- [ ] [US1] Create User model` (missing Task ID)
+- ❌ WRONG: `- [ ] T001 [US1] Create model` (missing file path)
+
+### Task Organization
+
+1. **From User Stories (spec.md)** - PRIMARY ORGANIZATION:
+   - Each user story (P1, P2, P3...) gets its own phase
+   - Map all related components to their story:
+     - Models needed for that story
+     - Services needed for that story
+     - Interfaces/UI needed for that story
+     - If tests requested: Tests specific to that story
+   - Mark story dependencies (most stories should be independent)
+
+2. **From Contracts**:
+   - Map each interface contract → to the user story it serves
+   - If tests requested: Each interface contract → contract test task [P] before implementation in that story's phase
+
+3. **From Data Model**:
+   - Map each entity to the user story(ies) that need it
+   - If entity serves multiple stories: Put in earliest story or Setup phase
+   - Relationships → service layer tasks in appropriate story phase
+
+4. **From Setup/Infrastructure**:
+   - Shared infrastructure → Setup phase (Phase 1)
+   - Foundational/blocking tasks → Foundational phase (Phase 2)
+   - Story-specific setup → within that story's phase
+
+### Phase Structure
+
+- **Phase 1**: Setup (project initialization)
+- **Phase 2**: Foundational (blocking prerequisites - MUST complete before user stories)
+- **Phase 3+**: User Stories in priority order (P1, P2, P3...)
+  - Within each story: Tests (if requested) → Models → Services → Endpoints → Integration
+  - Each phase should be a complete, independently testable increment
+- **Final Phase**: Polish & Cross-Cutting Concerns

+ 38 - 0
.claude/skills/speckit-taskstoissues/SKILL.md

@@ -0,0 +1,38 @@
+---
+name: "speckit-taskstoissues"
+description: "Convert existing tasks into actionable, dependency-ordered GitHub issues for the feature based on available design artifacts."
+argument-hint: "Optional filter or label for GitHub issues"
+compatibility: "Requires spec-kit project structure with .specify/ directory"
+metadata:
+  author: "github-spec-kit"
+  source: "templates/commands/taskstoissues.md"
+user-invocable: true
+disable-model-invocation: true
+---
+
+
+## User Input
+
+```text
+$ARGUMENTS
+```
+
+You **MUST** consider the user input before proceeding (if not empty).
+
+## Outline
+
+1. Run `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\''m Groot' (or double-quote if possible: "I'm Groot").
+1. From the executed script, extract the path to **tasks**.
+1. Get the Git remote by running:
+
+```bash
+git config --get remote.origin.url
+```
+
+> [!CAUTION]
+> ONLY PROCEED TO NEXT STEPS IF THE REMOTE IS A GITHUB URL
+
+1. For each task in the list, use the GitHub MCP server to create a new issue in the repository that is representative of the Git remote.
+
+> [!CAUTION]
+> UNDER NO CIRCUMSTANCES EVER CREATE ISSUES IN REPOSITORIES THAT DO NOT MATCH THE REMOTE URL

+ 31 - 30
.gitignore

@@ -1,65 +1,67 @@
-# IntelliJ IDEA
-.idea/vcs.xml
-.idea/misc.xml
-.idea/jpa-buddy.xml
-.idea/jarRepositories.xml
-.idea/encodings.xml
-.idea/compiler.xml
-.idea/editorJumperProjectSettings.xml
 
+# IntelliJ IDEA
 # Maven / Spring Boot
-target/
 *.class
+.idea/compiler.xml
+.idea/editorJumperProjectSettings.xml
+.idea/encodings.xml
+.idea/jarRepositories.xml
+.idea/jpa-buddy.xml
+.idea/misc.xml
+.idea/vcs.xml
+.superpowers/
+/.claude/*.json
+/.claude/settings.local.json
+/.gitignore
 /nul
-/ruoyi-admin/target/classes/META-INF/*.properties
-/ruoyi-admin/target/classes/*.yml
+/ruoyi-admin/target/classes
 /ruoyi-admin/target/classes/*.txt
 /ruoyi-admin/target/classes/*.xml
-/ruoyi-admin/target/classes/mybatis/*.xml
-/ruoyi-generator/target/classes/*.yml
-/ruoyi-generator/target/classes/mapper/generator/*.xml
-/ruoyi-generator/target/classes/vm/java/*.vm
-/ruoyi-generator/target/classes/vm/js/*.vm
-/ruoyi-generator/target/classes/vm/sql/*.vm
-/ruoyi-generator/target/classes/vm/vue/*.vm
-/ruoyi-generator/target/classes/vm/vue/v3/*.vm
-/ruoyi-generator/target/classes/vm/vue/v3/*.txt
-/ruoyi-generator/target/classes/vm/xml/*.vm
-/ruoyi-quartz/target/classes/mapper/quartz/*.xml
-/ruoyi-system/target/classes/mapper/Billing/*.xml
-/ruoyi-system/target/classes/mapper/feeds/*.xml
-/ruoyi-system/target/classes/mapper/infouser/*.xml
-/ruoyi-system/target/classes/mapper/system/*.xml
-/.claude/*.json
-/ruoyi-admin/target/classes
+/ruoyi-admin/target/classes/*.yml
 /ruoyi-admin/target/classes/META-INF
+/ruoyi-admin/target/classes/META-INF/*.properties
 /ruoyi-admin/target/classes/META-INF/spring-devtools.properties
 /ruoyi-admin/target/classes/application-druid.yml
 /ruoyi-admin/target/classes/banner.txt
 /ruoyi-admin/target/classes/logback.xml
+/ruoyi-admin/target/classes/mybatis/*.xml
 /ruoyi-admin/target/classes/mybatis/mybatis-config.xml
+/ruoyi-generator/target/classes/*.yml
 /ruoyi-generator/target/classes/generator.yml
+/ruoyi-generator/target/classes/mapper/generator/*.xml
 /ruoyi-generator/target/classes/mapper/generator/GenTableColumnMapper.xml
 /ruoyi-generator/target/classes/mapper/generator/GenTableMapper.xml
+/ruoyi-generator/target/classes/vm/java/*.vm
 /ruoyi-generator/target/classes/vm/java/controller.java.vm
 /ruoyi-generator/target/classes/vm/java/domain.java.vm
 /ruoyi-generator/target/classes/vm/java/mapper.java.vm
 /ruoyi-generator/target/classes/vm/java/service.java.vm
 /ruoyi-generator/target/classes/vm/java/serviceImpl.java.vm
 /ruoyi-generator/target/classes/vm/java/sub-domain.java.vm
+/ruoyi-generator/target/classes/vm/js/*.vm
 /ruoyi-generator/target/classes/vm/js/api.js.vm
+/ruoyi-generator/target/classes/vm/sql/*.vm
 /ruoyi-generator/target/classes/vm/sql/sql.vm
+/ruoyi-generator/target/classes/vm/vue/*.vm
 /ruoyi-generator/target/classes/vm/vue/index-tree.vue.vm
 /ruoyi-generator/target/classes/vm/vue/index.vue.vm
+/ruoyi-generator/target/classes/vm/vue/v3/*.txt
+/ruoyi-generator/target/classes/vm/vue/v3/*.vm
 /ruoyi-generator/target/classes/vm/vue/v3/index-tree.vue.vm
 /ruoyi-generator/target/classes/vm/vue/v3/index.vue.vm
 /ruoyi-generator/target/classes/vm/vue/v3/readme.txt
+/ruoyi-generator/target/classes/vm/xml/*.vm
 /ruoyi-generator/target/classes/vm/xml/mapper.xml.vm
+/ruoyi-quartz/target/classes/mapper/quartz/*.xml
 /ruoyi-quartz/target/classes/mapper/quartz/SysJobLogMapper.xml
 /ruoyi-quartz/target/classes/mapper/quartz/SysJobMapper.xml
+/ruoyi-system/target/classes/mapper/Billing/*.xml
 /ruoyi-system/target/classes/mapper/Billing/UserBillingMapper.xml
+/ruoyi-system/target/classes/mapper/feeds/*.xml
 /ruoyi-system/target/classes/mapper/feeds/SocialFeedbackMapper.xml
+/ruoyi-system/target/classes/mapper/infouser/*.xml
 /ruoyi-system/target/classes/mapper/infouser/InfoUserMapper.xml
+/ruoyi-system/target/classes/mapper/system/*.xml
 /ruoyi-system/target/classes/mapper/system/AppDownloadMapper.xml
 /ruoyi-system/target/classes/mapper/system/AppVersionMapper.xml
 /ruoyi-system/target/classes/mapper/system/BankCardMapper.xml
@@ -112,5 +114,4 @@ target/
 /ruoyi-system/target/classes/mapper/system/VipUserMapper.xml
 /ruoyi-system/target/classes/mapper/system/VipUserQuanyiMapper.xml
 /ruoyi-system/target/classes/mapper/system/WalletTransactionMapper.xml
-/.claude/settings.local.json
-/.gitignore
+target/

+ 10 - 0
.specify/init-options.json

@@ -0,0 +1,10 @@
+{
+  "ai": "claude",
+  "ai_skills": true,
+  "branch_numbering": "sequential",
+  "here": true,
+  "integration": "claude",
+  "preset": null,
+  "script": "ps",
+  "speckit_version": "0.5.1.dev0"
+}

+ 7 - 0
.specify/integration.json

@@ -0,0 +1,7 @@
+{
+  "integration": "claude",
+  "version": "0.5.1.dev0",
+  "scripts": {
+    "update-context": ".specify/integrations/claude/scripts/update-context.ps1"
+  }
+}

+ 18 - 0
.specify/integrations/claude.manifest.json

@@ -0,0 +1,18 @@
+{
+  "integration": "claude",
+  "version": "0.5.1.dev0",
+  "installed_at": "2026-04-28T01:07:03.106717+00:00",
+  "files": {
+    ".claude/skills/speckit-analyze/SKILL.md": "ee6710db85b3cef4adaa4890a78b40dcf05b959b91068694d8778d5b3ef1a669",
+    ".claude/skills/speckit-checklist/SKILL.md": "5d49113ce275f0e9ab75af133eb7d0bae43976c41a1c2f57e04c5cfd28d260cb",
+    ".claude/skills/speckit-clarify/SKILL.md": "46347a788d9baa1731f1de602fbd65fa6fe208c4d2f18b8534ab015abd3f8562",
+    ".claude/skills/speckit-constitution/SKILL.md": "0587314f660dc731c9c8798d6e7eb6e3fd22957fa466e989e4d8d02ee392acbf",
+    ".claude/skills/speckit-implement/SKILL.md": "da049e25017a1e3c8548cbf5809ca5617b48fa66b6af14fa18860a908c1d41c1",
+    ".claude/skills/speckit-plan/SKILL.md": "9a09a9ba95ed5f571f10f2dda039c10cf3cf539be27f7e3884f0d902be94b71e",
+    ".claude/skills/speckit-specify/SKILL.md": "f30c94d605e480a84621fffef2c9f547163537b6d00549fa32ac141b4a4e30c8",
+    ".claude/skills/speckit-tasks/SKILL.md": "4d28cdf0619b57bdc69f3b67da00cc23a622f63c04ef81cf84c3e84aaa5a24ef",
+    ".claude/skills/speckit-taskstoissues/SKILL.md": "c9273d9c412dd7905fa7883e0b4305ba6a6fe4eab46bb4c6ba232b45454a555d",
+    ".specify/integrations/claude/scripts/update-context.ps1": "8bce5081fe27ebf414d4eaf127d91b5540b00d24dde4fe1e303e8eb26ad5211a",
+    ".specify/integrations/claude/scripts/update-context.sh": "21a5aa3fc644f693a29d35975ce21e5a949cdc1d0258b11c21940754c3644fa6"
+  }
+}

+ 23 - 0
.specify/integrations/claude/scripts/update-context.ps1

@@ -0,0 +1,23 @@
+# update-context.ps1 — Claude Code integration: create/update CLAUDE.md
+#
+# Thin wrapper that delegates to the shared update-agent-context script.
+# Activated in Stage 7 when the shared script uses integration.json dispatch.
+#
+# Until then, this delegates to the shared script as a subprocess.
+
+$ErrorActionPreference = 'Stop'
+
+# Derive repo root from script location (walks up to find .specify/)
+$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
+$repoRoot = try { git rev-parse --show-toplevel 2>$null } catch { $null }
+# If git did not return a repo root, or the git root does not contain .specify,
+# fall back to walking up from the script directory to find the initialized project root.
+if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot '.specify'))) {
+    $repoRoot = $scriptDir
+    $fsRoot = [System.IO.Path]::GetPathRoot($repoRoot)
+    while ($repoRoot -and $repoRoot -ne $fsRoot -and -not (Test-Path (Join-Path $repoRoot '.specify'))) {
+        $repoRoot = Split-Path -Parent $repoRoot
+    }
+}
+
+& "$repoRoot/.specify/scripts/powershell/update-agent-context.ps1" -AgentType claude

+ 28 - 0
.specify/integrations/claude/scripts/update-context.sh

@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# update-context.sh — Claude Code integration: create/update CLAUDE.md
+#
+# Thin wrapper that delegates to the shared update-agent-context script.
+# Activated in Stage 7 when the shared script uses integration.json dispatch.
+#
+# Until then, this delegates to the shared script as a subprocess.
+
+set -euo pipefail
+
+# Derive repo root from script location (walks up to find .specify/)
+_script_dir="$(cd "$(dirname "$0")" && pwd)"
+_root="$_script_dir"
+while [ "$_root" != "/" ] && [ ! -d "$_root/.specify" ]; do _root="$(dirname "$_root")"; done
+if [ -z "${REPO_ROOT:-}" ]; then
+  if [ -d "$_root/.specify" ]; then
+    REPO_ROOT="$_root"
+  else
+    git_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
+    if [ -n "$git_root" ] && [ -d "$git_root/.specify" ]; then
+      REPO_ROOT="$git_root"
+    else
+      REPO_ROOT="$_root"
+    fi
+  fi
+fi
+
+exec "$REPO_ROOT/.specify/scripts/bash/update-agent-context.sh" claude

+ 18 - 0
.specify/integrations/speckit.manifest.json

@@ -0,0 +1,18 @@
+{
+  "integration": "speckit",
+  "version": "0.5.1.dev0",
+  "installed_at": "2026-04-28T01:07:03.130714+00:00",
+  "files": {
+    ".specify/scripts/powershell/check-prerequisites.ps1": "bcb37804b0757c37799b65a9321c1d3fb7b7ddcab6703c55c5b9a142c9166bf1",
+    ".specify/scripts/powershell/common.ps1": "e6f40ffb201144fdb0cf252809cf5066e6510a5f015228f0b2e74e84ca590ed3",
+    ".specify/scripts/powershell/create-new-feature.ps1": "de971f5c649948654b99cebc8caf50ba553b016a3b886e97b1ee09d8d80e7233",
+    ".specify/scripts/powershell/setup-plan.ps1": "c13ec3f33330e74aa088979c69bf35fe641301aaa50b2c1203c10ce94bcad338",
+    ".specify/scripts/powershell/update-agent-context.ps1": "42db3401c2869d8c6e4a77bf2e4d744afca9aff472cc2ae5b360aeaccc3c4e07",
+    ".specify/templates/agent-file-template.md": "55ed438c2e861444ef22f45fe5238f3ebf0dc1cb6e53067d7232fbbf4ce82892",
+    ".specify/templates/checklist-template.md": "312eee8291dfa984b21f95ddd0ca778e7a1f0b3a64bfc470d79762a3e3f5d7b8",
+    ".specify/templates/constitution-template.md": "ce7549540fa45543cca797a150201d868e64495fdff39dc38246fb17bd4024b3",
+    ".specify/templates/plan-template.md": "873e84b226fe3d24afe28046931b20db9bbb9210366428dc958a515349ed6e68",
+    ".specify/templates/spec-template.md": "785dc50d856dd92d6515eca0761e16dce0c9ba0a3cd07154fd33eae77932422a",
+    ".specify/templates/tasks-template.md": "5da92ac1fbf5be2f9018a5064497995bf3592761ccb6b3951503c63d851297e8"
+  }
+}

+ 50 - 0
.specify/memory/constitution.md

@@ -0,0 +1,50 @@
+# [PROJECT_NAME] Constitution
+<!-- Example: Spec Constitution, TaskFlow Constitution, etc. -->
+
+## Core Principles
+
+### [PRINCIPLE_1_NAME]
+<!-- Example: I. Library-First -->
+[PRINCIPLE_1_DESCRIPTION]
+<!-- Example: Every feature starts as a standalone library; Libraries must be self-contained, independently testable, documented; Clear purpose required - no organizational-only libraries -->
+
+### [PRINCIPLE_2_NAME]
+<!-- Example: II. CLI Interface -->
+[PRINCIPLE_2_DESCRIPTION]
+<!-- Example: Every library exposes functionality via CLI; Text in/out protocol: stdin/args → stdout, errors → stderr; Support JSON + human-readable formats -->
+
+### [PRINCIPLE_3_NAME]
+<!-- Example: III. Test-First (NON-NEGOTIABLE) -->
+[PRINCIPLE_3_DESCRIPTION]
+<!-- Example: TDD mandatory: Tests written → User approved → Tests fail → Then implement; Red-Green-Refactor cycle strictly enforced -->
+
+### [PRINCIPLE_4_NAME]
+<!-- Example: IV. Integration Testing -->
+[PRINCIPLE_4_DESCRIPTION]
+<!-- Example: Focus areas requiring integration tests: New library contract tests, Contract changes, Inter-service communication, Shared schemas -->
+
+### [PRINCIPLE_5_NAME]
+<!-- Example: V. Observability, VI. Versioning & Breaking Changes, VII. Simplicity -->
+[PRINCIPLE_5_DESCRIPTION]
+<!-- Example: Text I/O ensures debuggability; Structured logging required; Or: MAJOR.MINOR.BUILD format; Or: Start simple, YAGNI principles -->
+
+## [SECTION_2_NAME]
+<!-- Example: Additional Constraints, Security Requirements, Performance Standards, etc. -->
+
+[SECTION_2_CONTENT]
+<!-- Example: Technology stack requirements, compliance standards, deployment policies, etc. -->
+
+## [SECTION_3_NAME]
+<!-- Example: Development Workflow, Review Process, Quality Gates, etc. -->
+
+[SECTION_3_CONTENT]
+<!-- Example: Code review requirements, testing gates, deployment approval process, etc. -->
+
+## Governance
+<!-- Example: Constitution supersedes all other practices; Amendments require documentation, approval, migration plan -->
+
+[GOVERNANCE_RULES]
+<!-- Example: All PRs/reviews must verify compliance; Complexity must be justified; Use [GUIDANCE_FILE] for runtime development guidance -->
+
+**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE]
+<!-- Example: Version: 2.1.1 | Ratified: 2025-06-13 | Last Amended: 2025-07-16 -->

+ 148 - 0
.specify/scripts/powershell/check-prerequisites.ps1

@@ -0,0 +1,148 @@
+#!/usr/bin/env pwsh
+
+# Consolidated prerequisite checking script (PowerShell)
+#
+# This script provides unified prerequisite checking for Spec-Driven Development workflow.
+# It replaces the functionality previously spread across multiple scripts.
+#
+# Usage: ./check-prerequisites.ps1 [OPTIONS]
+#
+# OPTIONS:
+#   -Json               Output in JSON format
+#   -RequireTasks       Require tasks.md to exist (for implementation phase)
+#   -IncludeTasks       Include tasks.md in AVAILABLE_DOCS list
+#   -PathsOnly          Only output path variables (no validation)
+#   -Help, -h           Show help message
+
+[CmdletBinding()]
+param(
+    [switch]$Json,
+    [switch]$RequireTasks,
+    [switch]$IncludeTasks,
+    [switch]$PathsOnly,
+    [switch]$Help
+)
+
+$ErrorActionPreference = 'Stop'
+
+# Show help if requested
+if ($Help) {
+    Write-Output @"
+Usage: check-prerequisites.ps1 [OPTIONS]
+
+Consolidated prerequisite checking for Spec-Driven Development workflow.
+
+OPTIONS:
+  -Json               Output in JSON format
+  -RequireTasks       Require tasks.md to exist (for implementation phase)
+  -IncludeTasks       Include tasks.md in AVAILABLE_DOCS list
+  -PathsOnly          Only output path variables (no prerequisite validation)
+  -Help, -h           Show this help message
+
+EXAMPLES:
+  # Check task prerequisites (plan.md required)
+  .\check-prerequisites.ps1 -Json
+  
+  # Check implementation prerequisites (plan.md + tasks.md required)
+  .\check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks
+  
+  # Get feature paths only (no validation)
+  .\check-prerequisites.ps1 -PathsOnly
+
+"@
+    exit 0
+}
+
+# Source common functions
+. "$PSScriptRoot/common.ps1"
+
+# Get feature paths and validate branch
+$paths = Get-FeaturePathsEnv
+
+if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GIT)) { 
+    exit 1 
+}
+
+# If paths-only mode, output paths and exit (support combined -Json -PathsOnly)
+if ($PathsOnly) {
+    if ($Json) {
+        [PSCustomObject]@{
+            REPO_ROOT    = $paths.REPO_ROOT
+            BRANCH       = $paths.CURRENT_BRANCH
+            FEATURE_DIR  = $paths.FEATURE_DIR
+            FEATURE_SPEC = $paths.FEATURE_SPEC
+            IMPL_PLAN    = $paths.IMPL_PLAN
+            TASKS        = $paths.TASKS
+        } | ConvertTo-Json -Compress
+    } else {
+        Write-Output "REPO_ROOT: $($paths.REPO_ROOT)"
+        Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
+        Write-Output "FEATURE_DIR: $($paths.FEATURE_DIR)"
+        Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
+        Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
+        Write-Output "TASKS: $($paths.TASKS)"
+    }
+    exit 0
+}
+
+# Validate required directories and files
+if (-not (Test-Path $paths.FEATURE_DIR -PathType Container)) {
+    Write-Output "ERROR: Feature directory not found: $($paths.FEATURE_DIR)"
+    Write-Output "Run /speckit.specify first to create the feature structure."
+    exit 1
+}
+
+if (-not (Test-Path $paths.IMPL_PLAN -PathType Leaf)) {
+    Write-Output "ERROR: plan.md not found in $($paths.FEATURE_DIR)"
+    Write-Output "Run /speckit.plan first to create the implementation plan."
+    exit 1
+}
+
+# Check for tasks.md if required
+if ($RequireTasks -and -not (Test-Path $paths.TASKS -PathType Leaf)) {
+    Write-Output "ERROR: tasks.md not found in $($paths.FEATURE_DIR)"
+    Write-Output "Run /speckit.tasks first to create the task list."
+    exit 1
+}
+
+# Build list of available documents
+$docs = @()
+
+# Always check these optional docs
+if (Test-Path $paths.RESEARCH) { $docs += 'research.md' }
+if (Test-Path $paths.DATA_MODEL) { $docs += 'data-model.md' }
+
+# Check contracts directory (only if it exists and has files)
+if ((Test-Path $paths.CONTRACTS_DIR) -and (Get-ChildItem -Path $paths.CONTRACTS_DIR -ErrorAction SilentlyContinue | Select-Object -First 1)) { 
+    $docs += 'contracts/' 
+}
+
+if (Test-Path $paths.QUICKSTART) { $docs += 'quickstart.md' }
+
+# Include tasks.md if requested and it exists
+if ($IncludeTasks -and (Test-Path $paths.TASKS)) { 
+    $docs += 'tasks.md' 
+}
+
+# Output results
+if ($Json) {
+    # JSON output
+    [PSCustomObject]@{ 
+        FEATURE_DIR = $paths.FEATURE_DIR
+        AVAILABLE_DOCS = $docs 
+    } | ConvertTo-Json -Compress
+} else {
+    # Text output
+    Write-Output "FEATURE_DIR:$($paths.FEATURE_DIR)"
+    Write-Output "AVAILABLE_DOCS:"
+    
+    # Show status of each potential document
+    Test-FileExists -Path $paths.RESEARCH -Description 'research.md' | Out-Null
+    Test-FileExists -Path $paths.DATA_MODEL -Description 'data-model.md' | Out-Null
+    Test-DirHasFiles -Path $paths.CONTRACTS_DIR -Description 'contracts/' | Out-Null
+    Test-FileExists -Path $paths.QUICKSTART -Description 'quickstart.md' | Out-Null
+    
+    if ($IncludeTasks) {
+        Test-FileExists -Path $paths.TASKS -Description 'tasks.md' | Out-Null
+    }
+}

+ 268 - 0
.specify/scripts/powershell/common.ps1

@@ -0,0 +1,268 @@
+#!/usr/bin/env pwsh
+# Common PowerShell functions analogous to common.sh
+
+# Find repository root by searching upward for .specify directory
+# This is the primary marker for spec-kit projects
+function Find-SpecifyRoot {
+    param([string]$StartDir = (Get-Location).Path)
+
+    # Normalize to absolute path to prevent issues with relative paths
+    # Use -LiteralPath to handle paths with wildcard characters ([, ], *, ?)
+    $resolved = Resolve-Path -LiteralPath $StartDir -ErrorAction SilentlyContinue
+    $current = if ($resolved) { $resolved.Path } else { $null }
+    if (-not $current) { return $null }
+
+    while ($true) {
+        if (Test-Path -LiteralPath (Join-Path $current ".specify") -PathType Container) {
+            return $current
+        }
+        $parent = Split-Path $current -Parent
+        if ([string]::IsNullOrEmpty($parent) -or $parent -eq $current) {
+            return $null
+        }
+        $current = $parent
+    }
+}
+
+# Get repository root, prioritizing .specify directory over git
+# This prevents using a parent git repo when spec-kit is initialized in a subdirectory
+function Get-RepoRoot {
+    # First, look for .specify directory (spec-kit's own marker)
+    $specifyRoot = Find-SpecifyRoot
+    if ($specifyRoot) {
+        return $specifyRoot
+    }
+
+    # Fallback to git if no .specify found
+    try {
+        $result = git rev-parse --show-toplevel 2>$null
+        if ($LASTEXITCODE -eq 0) {
+            return $result
+        }
+    } catch {
+        # Git command failed
+    }
+
+    # Final fallback to script location for non-git repos
+    # Use -LiteralPath to handle paths with wildcard characters
+    return (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "../../..")).Path
+}
+
+function Get-CurrentBranch {
+    # First check if SPECIFY_FEATURE environment variable is set
+    if ($env:SPECIFY_FEATURE) {
+        return $env:SPECIFY_FEATURE
+    }
+
+    # Then check git if available at the spec-kit root (not parent)
+    $repoRoot = Get-RepoRoot
+    if (Test-HasGit) {
+        try {
+            $result = git -C $repoRoot rev-parse --abbrev-ref HEAD 2>$null
+            if ($LASTEXITCODE -eq 0) {
+                return $result
+            }
+        } catch {
+            # Git command failed
+        }
+    }
+
+    # For non-git repos, try to find the latest feature directory
+    $specsDir = Join-Path $repoRoot "specs"
+    
+    if (Test-Path $specsDir) {
+        $latestFeature = ""
+        $highest = 0
+        $latestTimestamp = ""
+
+        Get-ChildItem -Path $specsDir -Directory | ForEach-Object {
+            if ($_.Name -match '^(\d{8}-\d{6})-') {
+                # Timestamp-based branch: compare lexicographically
+                $ts = $matches[1]
+                if ($ts -gt $latestTimestamp) {
+                    $latestTimestamp = $ts
+                    $latestFeature = $_.Name
+                }
+            } elseif ($_.Name -match '^(\d{3,})-') {
+                $num = [long]$matches[1]
+                if ($num -gt $highest) {
+                    $highest = $num
+                    # Only update if no timestamp branch found yet
+                    if (-not $latestTimestamp) {
+                        $latestFeature = $_.Name
+                    }
+                }
+            }
+        }
+
+        if ($latestFeature) {
+            return $latestFeature
+        }
+    }
+    
+    # Final fallback
+    return "main"
+}
+
+# Check if we have git available at the spec-kit root level
+# Returns true only if git is installed and the repo root is inside a git work tree
+# Handles both regular repos (.git directory) and worktrees/submodules (.git file)
+function Test-HasGit {
+    # First check if git command is available (before calling Get-RepoRoot which may use git)
+    if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
+        return $false
+    }
+    $repoRoot = Get-RepoRoot
+    # Check if .git exists (directory or file for worktrees/submodules)
+    # Use -LiteralPath to handle paths with wildcard characters
+    if (-not (Test-Path -LiteralPath (Join-Path $repoRoot ".git"))) {
+        return $false
+    }
+    # Verify it's actually a valid git work tree
+    try {
+        $null = git -C $repoRoot rev-parse --is-inside-work-tree 2>$null
+        return ($LASTEXITCODE -eq 0)
+    } catch {
+        return $false
+    }
+}
+
+function Test-FeatureBranch {
+    param(
+        [string]$Branch,
+        [bool]$HasGit = $true
+    )
+    
+    # For non-git repos, we can't enforce branch naming but still provide output
+    if (-not $HasGit) {
+        Write-Warning "[specify] Warning: Git repository not detected; skipped branch validation"
+        return $true
+    }
+    
+    # Accept sequential prefix (3+ digits) but exclude malformed timestamps
+    # Malformed: 7-or-8 digit date + 6-digit time with no trailing slug (e.g. "2026031-143022" or "20260319-143022")
+    $hasMalformedTimestamp = ($Branch -match '^[0-9]{7}-[0-9]{6}-') -or ($Branch -match '^(?:\d{7}|\d{8})-\d{6}$')
+    $isSequential = ($Branch -match '^[0-9]{3,}-') -and (-not $hasMalformedTimestamp)
+    if (-not $isSequential -and $Branch -notmatch '^\d{8}-\d{6}-') {
+        Write-Output "ERROR: Not on a feature branch. Current branch: $Branch"
+        Write-Output "Feature branches should be named like: 001-feature-name, 1234-feature-name, or 20260319-143022-feature-name"
+        return $false
+    }
+    return $true
+}
+
+function Get-FeatureDir {
+    param([string]$RepoRoot, [string]$Branch)
+    Join-Path $RepoRoot "specs/$Branch"
+}
+
+function Get-FeaturePathsEnv {
+    $repoRoot = Get-RepoRoot
+    $currentBranch = Get-CurrentBranch
+    $hasGit = Test-HasGit
+    $featureDir = Get-FeatureDir -RepoRoot $repoRoot -Branch $currentBranch
+    
+    [PSCustomObject]@{
+        REPO_ROOT     = $repoRoot
+        CURRENT_BRANCH = $currentBranch
+        HAS_GIT       = $hasGit
+        FEATURE_DIR   = $featureDir
+        FEATURE_SPEC  = Join-Path $featureDir 'spec.md'
+        IMPL_PLAN     = Join-Path $featureDir 'plan.md'
+        TASKS         = Join-Path $featureDir 'tasks.md'
+        RESEARCH      = Join-Path $featureDir 'research.md'
+        DATA_MODEL    = Join-Path $featureDir 'data-model.md'
+        QUICKSTART    = Join-Path $featureDir 'quickstart.md'
+        CONTRACTS_DIR = Join-Path $featureDir 'contracts'
+    }
+}
+
+function Test-FileExists {
+    param([string]$Path, [string]$Description)
+    if (Test-Path -Path $Path -PathType Leaf) {
+        Write-Output "  ✓ $Description"
+        return $true
+    } else {
+        Write-Output "  ✗ $Description"
+        return $false
+    }
+}
+
+function Test-DirHasFiles {
+    param([string]$Path, [string]$Description)
+    if ((Test-Path -Path $Path -PathType Container) -and (Get-ChildItem -Path $Path -ErrorAction SilentlyContinue | Where-Object { -not $_.PSIsContainer } | Select-Object -First 1)) {
+        Write-Output "  ✓ $Description"
+        return $true
+    } else {
+        Write-Output "  ✗ $Description"
+        return $false
+    }
+}
+
+# Resolve a template name to a file path using the priority stack:
+#   1. .specify/templates/overrides/
+#   2. .specify/presets/<preset-id>/templates/ (sorted by priority from .registry)
+#   3. .specify/extensions/<ext-id>/templates/
+#   4. .specify/templates/ (core)
+function Resolve-Template {
+    param(
+        [Parameter(Mandatory=$true)][string]$TemplateName,
+        [Parameter(Mandatory=$true)][string]$RepoRoot
+    )
+
+    $base = Join-Path $RepoRoot '.specify/templates'
+
+    # Priority 1: Project overrides
+    $override = Join-Path $base "overrides/$TemplateName.md"
+    if (Test-Path $override) { return $override }
+
+    # Priority 2: Installed presets (sorted by priority from .registry)
+    $presetsDir = Join-Path $RepoRoot '.specify/presets'
+    if (Test-Path $presetsDir) {
+        $registryFile = Join-Path $presetsDir '.registry'
+        $sortedPresets = @()
+        if (Test-Path $registryFile) {
+            try {
+                $registryData = Get-Content $registryFile -Raw | ConvertFrom-Json
+                $presets = $registryData.presets
+                if ($presets) {
+                    $sortedPresets = $presets.PSObject.Properties |
+                        Sort-Object { if ($null -ne $_.Value.priority) { $_.Value.priority } else { 10 } } |
+                        ForEach-Object { $_.Name }
+                }
+            } catch {
+                # Fallback: alphabetical directory order
+                $sortedPresets = @()
+            }
+        }
+
+        if ($sortedPresets.Count -gt 0) {
+            foreach ($presetId in $sortedPresets) {
+                $candidate = Join-Path $presetsDir "$presetId/templates/$TemplateName.md"
+                if (Test-Path $candidate) { return $candidate }
+            }
+        } else {
+            # Fallback: alphabetical directory order
+            foreach ($preset in Get-ChildItem -Path $presetsDir -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notlike '.*' }) {
+                $candidate = Join-Path $preset.FullName "templates/$TemplateName.md"
+                if (Test-Path $candidate) { return $candidate }
+            }
+        }
+    }
+
+    # Priority 3: Extension-provided templates
+    $extDir = Join-Path $RepoRoot '.specify/extensions'
+    if (Test-Path $extDir) {
+        foreach ($ext in Get-ChildItem -Path $extDir -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notlike '.*' } | Sort-Object Name) {
+            $candidate = Join-Path $ext.FullName "templates/$TemplateName.md"
+            if (Test-Path $candidate) { return $candidate }
+        }
+    }
+
+    # Priority 4: Core templates
+    $core = Join-Path $base "$TemplateName.md"
+    if (Test-Path $core) { return $core }
+
+    return $null
+}
+

+ 378 - 0
.specify/scripts/powershell/create-new-feature.ps1

@@ -0,0 +1,378 @@
+#!/usr/bin/env pwsh
+# Create a new feature
+[CmdletBinding()]
+param(
+    [switch]$Json,
+    [switch]$AllowExistingBranch,
+    [switch]$DryRun,
+    [string]$ShortName,
+    [Parameter()]
+    [long]$Number = 0,
+    [switch]$Timestamp,
+    [switch]$Help,
+    [Parameter(Position = 0, ValueFromRemainingArguments = $true)]
+    [string[]]$FeatureDescription
+)
+$ErrorActionPreference = 'Stop'
+
+# Show help if requested
+if ($Help) {
+    Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
+    Write-Host ""
+    Write-Host "Options:"
+    Write-Host "  -Json               Output in JSON format"
+    Write-Host "  -DryRun             Compute branch name and paths without creating branches, directories, or files"
+    Write-Host "  -AllowExistingBranch  Switch to branch if it already exists instead of failing"
+    Write-Host "  -ShortName <name>   Provide a custom short name (2-4 words) for the branch"
+    Write-Host "  -Number N           Specify branch number manually (overrides auto-detection)"
+    Write-Host "  -Timestamp          Use timestamp prefix (YYYYMMDD-HHMMSS) instead of sequential numbering"
+    Write-Host "  -Help               Show this help message"
+    Write-Host ""
+    Write-Host "Examples:"
+    Write-Host "  ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'"
+    Write-Host "  ./create-new-feature.ps1 'Implement OAuth2 integration for API'"
+    Write-Host "  ./create-new-feature.ps1 -Timestamp -ShortName 'user-auth' 'Add user authentication'"
+    exit 0
+}
+
+# Check if feature description provided
+if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) {
+    Write-Error "Usage: ./create-new-feature.ps1 [-Json] [-DryRun] [-AllowExistingBranch] [-ShortName <name>] [-Number N] [-Timestamp] <feature description>"
+    exit 1
+}
+
+$featureDesc = ($FeatureDescription -join ' ').Trim()
+
+# Validate description is not empty after trimming (e.g., user passed only whitespace)
+if ([string]::IsNullOrWhiteSpace($featureDesc)) {
+    Write-Error "Error: Feature description cannot be empty or contain only whitespace"
+    exit 1
+}
+
+function Get-HighestNumberFromSpecs {
+    param([string]$SpecsDir)
+
+    [long]$highest = 0
+    if (Test-Path $SpecsDir) {
+        Get-ChildItem -Path $SpecsDir -Directory | ForEach-Object {
+            # Match sequential prefixes (>=3 digits), but skip timestamp dirs.
+            if ($_.Name -match '^(\d{3,})-' -and $_.Name -notmatch '^\d{8}-\d{6}-') {
+                [long]$num = 0
+                if ([long]::TryParse($matches[1], [ref]$num) -and $num -gt $highest) {
+                    $highest = $num
+                }
+            }
+        }
+    }
+    return $highest
+}
+
+# Extract the highest sequential feature number from a list of branch/ref names.
+# Shared by Get-HighestNumberFromBranches and Get-HighestNumberFromRemoteRefs.
+function Get-HighestNumberFromNames {
+    param([string[]]$Names)
+
+    [long]$highest = 0
+    foreach ($name in $Names) {
+        if ($name -match '^(\d{3,})-' -and $name -notmatch '^\d{8}-\d{6}-') {
+            [long]$num = 0
+            if ([long]::TryParse($matches[1], [ref]$num) -and $num -gt $highest) {
+                $highest = $num
+            }
+        }
+    }
+    return $highest
+}
+
+function Get-HighestNumberFromBranches {
+    param()
+
+    try {
+        $branches = git branch -a 2>$null
+        if ($LASTEXITCODE -eq 0 -and $branches) {
+            $cleanNames = $branches | ForEach-Object {
+                $_.Trim() -replace '^\*?\s+', '' -replace '^remotes/[^/]+/', ''
+            }
+            return Get-HighestNumberFromNames -Names $cleanNames
+        }
+    } catch {
+        Write-Verbose "Could not check Git branches: $_"
+    }
+    return 0
+}
+
+function Get-HighestNumberFromRemoteRefs {
+    [long]$highest = 0
+    try {
+        $remotes = git remote 2>$null
+        if ($remotes) {
+            foreach ($remote in $remotes) {
+                $env:GIT_TERMINAL_PROMPT = '0'
+                $refs = git ls-remote --heads $remote 2>$null
+                $env:GIT_TERMINAL_PROMPT = $null
+                if ($LASTEXITCODE -eq 0 -and $refs) {
+                    $refNames = $refs | ForEach-Object {
+                        if ($_ -match 'refs/heads/(.+)$') { $matches[1] }
+                    } | Where-Object { $_ }
+                    $remoteHighest = Get-HighestNumberFromNames -Names $refNames
+                    if ($remoteHighest -gt $highest) { $highest = $remoteHighest }
+                }
+            }
+        }
+    } catch {
+        Write-Verbose "Could not query remote refs: $_"
+    }
+    return $highest
+}
+
+# Return next available branch number. When SkipFetch is true, queries remotes
+# via ls-remote (read-only) instead of fetching.
+function Get-NextBranchNumber {
+    param(
+        [string]$SpecsDir,
+        [switch]$SkipFetch
+    )
+
+    if ($SkipFetch) {
+        # Side-effect-free: query remotes via ls-remote
+        $highestBranch = Get-HighestNumberFromBranches
+        $highestRemote = Get-HighestNumberFromRemoteRefs
+        $highestBranch = [Math]::Max($highestBranch, $highestRemote)
+    } else {
+        # Fetch all remotes to get latest branch info (suppress errors if no remotes)
+        try {
+            git fetch --all --prune 2>$null | Out-Null
+        } catch {
+            # Ignore fetch errors
+        }
+        $highestBranch = Get-HighestNumberFromBranches
+    }
+
+    # Get highest number from ALL specs (not just matching short name)
+    $highestSpec = Get-HighestNumberFromSpecs -SpecsDir $SpecsDir
+
+    # Take the maximum of both
+    $maxNum = [Math]::Max($highestBranch, $highestSpec)
+
+    # Return next number
+    return $maxNum + 1
+}
+
+function ConvertTo-CleanBranchName {
+    param([string]$Name)
+
+    return $Name.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', ''
+}
+# Load common functions (includes Get-RepoRoot, Test-HasGit, Resolve-Template)
+. "$PSScriptRoot/common.ps1"
+
+# Use common.ps1 functions which prioritize .specify over git
+$repoRoot = Get-RepoRoot
+
+# Check if git is available at this repo root (not a parent)
+$hasGit = Test-HasGit
+
+Set-Location $repoRoot
+
+$specsDir = Join-Path $repoRoot 'specs'
+if (-not $DryRun) {
+    New-Item -ItemType Directory -Path $specsDir -Force | Out-Null
+}
+
+# Function to generate branch name with stop word filtering and length filtering
+function Get-BranchName {
+    param([string]$Description)
+
+    # Common stop words to filter out
+    $stopWords = @(
+        'i', 'a', 'an', 'the', 'to', 'for', 'of', 'in', 'on', 'at', 'by', 'with', 'from',
+        'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
+        'do', 'does', 'did', 'will', 'would', 'should', 'could', 'can', 'may', 'might', 'must', 'shall',
+        'this', 'that', 'these', 'those', 'my', 'your', 'our', 'their',
+        'want', 'need', 'add', 'get', 'set'
+    )
+
+    # Convert to lowercase and extract words (alphanumeric only)
+    $cleanName = $Description.ToLower() -replace '[^a-z0-9\s]', ' '
+    $words = $cleanName -split '\s+' | Where-Object { $_ }
+
+    # Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
+    $meaningfulWords = @()
+    foreach ($word in $words) {
+        # Skip stop words
+        if ($stopWords -contains $word) { continue }
+
+        # Keep words that are length >= 3 OR appear as uppercase in original (likely acronyms)
+        if ($word.Length -ge 3) {
+            $meaningfulWords += $word
+        } elseif ($Description -match "\b$($word.ToUpper())\b") {
+            # Keep short words if they appear as uppercase in original (likely acronyms)
+            $meaningfulWords += $word
+        }
+    }
+
+    # If we have meaningful words, use first 3-4 of them
+    if ($meaningfulWords.Count -gt 0) {
+        $maxWords = if ($meaningfulWords.Count -eq 4) { 4 } else { 3 }
+        $result = ($meaningfulWords | Select-Object -First $maxWords) -join '-'
+        return $result
+    } else {
+        # Fallback to original logic if no meaningful words found
+        $result = ConvertTo-CleanBranchName -Name $Description
+        $fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3
+        return [string]::Join('-', $fallbackWords)
+    }
+}
+
+# Generate branch name
+if ($ShortName) {
+    # Use provided short name, just clean it up
+    $branchSuffix = ConvertTo-CleanBranchName -Name $ShortName
+} else {
+    # Generate from description with smart filtering
+    $branchSuffix = Get-BranchName -Description $featureDesc
+}
+
+# Warn if -Number and -Timestamp are both specified
+if ($Timestamp -and $Number -ne 0) {
+    Write-Warning "[specify] Warning: -Number is ignored when -Timestamp is used"
+    $Number = 0
+}
+
+# Determine branch prefix
+if ($Timestamp) {
+    $featureNum = Get-Date -Format 'yyyyMMdd-HHmmss'
+    $branchName = "$featureNum-$branchSuffix"
+} else {
+    # Determine branch number
+    if ($Number -eq 0) {
+        if ($DryRun -and $hasGit) {
+            # Dry-run: query remotes via ls-remote (side-effect-free, no fetch)
+            $Number = Get-NextBranchNumber -SpecsDir $specsDir -SkipFetch
+        } elseif ($DryRun) {
+            # Dry-run without git: local spec dirs only
+            $Number = (Get-HighestNumberFromSpecs -SpecsDir $specsDir) + 1
+        } elseif ($hasGit) {
+            # Check existing branches on remotes
+            $Number = Get-NextBranchNumber -SpecsDir $specsDir
+        } else {
+            # Fall back to local directory check
+            $Number = (Get-HighestNumberFromSpecs -SpecsDir $specsDir) + 1
+        }
+    }
+
+    $featureNum = ('{0:000}' -f $Number)
+    $branchName = "$featureNum-$branchSuffix"
+}
+
+# GitHub enforces a 244-byte limit on branch names
+# Validate and truncate if necessary
+$maxBranchLength = 244
+if ($branchName.Length -gt $maxBranchLength) {
+    # Calculate how much we need to trim from suffix
+    # Account for prefix length: timestamp (15) + hyphen (1) = 16, or sequential (3) + hyphen (1) = 4
+    $prefixLength = $featureNum.Length + 1
+    $maxSuffixLength = $maxBranchLength - $prefixLength
+
+    # Truncate suffix
+    $truncatedSuffix = $branchSuffix.Substring(0, [Math]::Min($branchSuffix.Length, $maxSuffixLength))
+    # Remove trailing hyphen if truncation created one
+    $truncatedSuffix = $truncatedSuffix -replace '-$', ''
+
+    $originalBranchName = $branchName
+    $branchName = "$featureNum-$truncatedSuffix"
+
+    Write-Warning "[specify] Branch name exceeded GitHub's 244-byte limit"
+    Write-Warning "[specify] Original: $originalBranchName ($($originalBranchName.Length) bytes)"
+    Write-Warning "[specify] Truncated to: $branchName ($($branchName.Length) bytes)"
+}
+
+$featureDir = Join-Path $specsDir $branchName
+$specFile = Join-Path $featureDir 'spec.md'
+
+if (-not $DryRun) {
+    if ($hasGit) {
+        $branchCreated = $false
+        $branchCreateError = ''
+        try {
+            $branchCreateError = git checkout -q -b $branchName 2>&1 | Out-String
+            if ($LASTEXITCODE -eq 0) {
+                $branchCreated = $true
+            }
+        } catch {
+            $branchCreateError = $_.Exception.Message
+        }
+
+        if (-not $branchCreated) {
+            $currentBranch = ''
+            try { $currentBranch = (git rev-parse --abbrev-ref HEAD 2>$null).Trim() } catch {}
+            # Check if branch already exists
+            $existingBranch = git branch --list $branchName 2>$null
+            if ($existingBranch) {
+                if ($AllowExistingBranch) {
+                    # If we're already on the branch, continue without another checkout.
+                    if ($currentBranch -eq $branchName) {
+                        # Already on the target branch — nothing to do
+                    } else {
+                        # Otherwise switch to the existing branch instead of failing.
+                        git checkout -q $branchName 2>$null | Out-Null
+                        if ($LASTEXITCODE -ne 0) {
+                            Write-Error "Error: Branch '$branchName' exists but could not be checked out. Resolve any uncommitted changes or conflicts and try again."
+                            exit 1
+                        }
+                    }
+                } elseif ($Timestamp) {
+                    Write-Error "Error: Branch '$branchName' already exists. Rerun to get a new timestamp or use a different -ShortName."
+                    exit 1
+                } else {
+                    Write-Error "Error: Branch '$branchName' already exists. Please use a different feature name or specify a different number with -Number."
+                    exit 1
+                }
+            } else {
+                if ($branchCreateError) {
+                    Write-Error "Error: Failed to create git branch '$branchName'.`n$($branchCreateError.Trim())"
+                } else {
+                    Write-Error "Error: Failed to create git branch '$branchName'. Please check your git configuration and try again."
+                }
+                exit 1
+            }
+        }
+    } else {
+        Write-Warning "[specify] Warning: Git repository not detected; skipped branch creation for $branchName"
+    }
+
+    New-Item -ItemType Directory -Path $featureDir -Force | Out-Null
+
+    if (-not (Test-Path -PathType Leaf $specFile)) {
+        $template = Resolve-Template -TemplateName 'spec-template' -RepoRoot $repoRoot
+        if ($template -and (Test-Path $template)) {
+            Copy-Item $template $specFile -Force
+        } else {
+            New-Item -ItemType File -Path $specFile -Force | Out-Null
+        }
+    }
+
+    # Set the SPECIFY_FEATURE environment variable for the current session
+    $env:SPECIFY_FEATURE = $branchName
+}
+
+if ($Json) {
+    $obj = [PSCustomObject]@{
+        BRANCH_NAME = $branchName
+        SPEC_FILE = $specFile
+        FEATURE_NUM = $featureNum
+        HAS_GIT = $hasGit
+    }
+    if ($DryRun) {
+        $obj | Add-Member -NotePropertyName 'DRY_RUN' -NotePropertyValue $true
+    }
+    $obj | ConvertTo-Json -Compress
+} else {
+    Write-Output "BRANCH_NAME: $branchName"
+    Write-Output "SPEC_FILE: $specFile"
+    Write-Output "FEATURE_NUM: $featureNum"
+    Write-Output "HAS_GIT: $hasGit"
+    if (-not $DryRun) {
+        Write-Output "SPECIFY_FEATURE environment variable set to: $branchName"
+    }
+}

+ 61 - 0
.specify/scripts/powershell/setup-plan.ps1

@@ -0,0 +1,61 @@
+#!/usr/bin/env pwsh
+# Setup implementation plan for a feature
+
+[CmdletBinding()]
+param(
+    [switch]$Json,
+    [switch]$Help
+)
+
+$ErrorActionPreference = 'Stop'
+
+# Show help if requested
+if ($Help) {
+    Write-Output "Usage: ./setup-plan.ps1 [-Json] [-Help]"
+    Write-Output "  -Json     Output results in JSON format"
+    Write-Output "  -Help     Show this help message"
+    exit 0
+}
+
+# Load common functions
+. "$PSScriptRoot/common.ps1"
+
+# Get all paths and variables from common functions
+$paths = Get-FeaturePathsEnv
+
+# Check if we're on a proper feature branch (only for git repos)
+if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit $paths.HAS_GIT)) { 
+    exit 1 
+}
+
+# Ensure the feature directory exists
+New-Item -ItemType Directory -Path $paths.FEATURE_DIR -Force | Out-Null
+
+# Copy plan template if it exists, otherwise note it or create empty file
+$template = Resolve-Template -TemplateName 'plan-template' -RepoRoot $paths.REPO_ROOT
+if ($template -and (Test-Path $template)) { 
+    Copy-Item $template $paths.IMPL_PLAN -Force
+    Write-Output "Copied plan template to $($paths.IMPL_PLAN)"
+} else {
+    Write-Warning "Plan template not found"
+    # Create a basic plan file if template doesn't exist
+    New-Item -ItemType File -Path $paths.IMPL_PLAN -Force | Out-Null
+}
+
+# Output results
+if ($Json) {
+    $result = [PSCustomObject]@{ 
+        FEATURE_SPEC = $paths.FEATURE_SPEC
+        IMPL_PLAN = $paths.IMPL_PLAN
+        SPECS_DIR = $paths.FEATURE_DIR
+        BRANCH = $paths.CURRENT_BRANCH
+        HAS_GIT = $paths.HAS_GIT
+    }
+    $result | ConvertTo-Json -Compress
+} else {
+    Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
+    Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
+    Write-Output "SPECS_DIR: $($paths.FEATURE_DIR)"
+    Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
+    Write-Output "HAS_GIT: $($paths.HAS_GIT)"
+}

+ 513 - 0
.specify/scripts/powershell/update-agent-context.ps1

@@ -0,0 +1,513 @@
+#!/usr/bin/env pwsh
+<#!
+.SYNOPSIS
+Update agent context files with information from plan.md (PowerShell version)
+
+.DESCRIPTION
+Mirrors the behavior of scripts/bash/update-agent-context.sh:
+ 1. Environment Validation
+ 2. Plan Data Extraction
+ 3. Agent File Management (create from template or update existing)
+ 4. Content Generation (technology stack, recent changes, timestamp)
+ 5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, junie, kilocode, auggie, roo, codebuddy, amp, shai, tabnine, kiro-cli, agy, bob, vibe, qodercli, kimi, trae, pi, iflow, forge, generic)
+
+.PARAMETER AgentType
+Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
+
+.EXAMPLE
+./update-agent-context.ps1 -AgentType claude
+
+.EXAMPLE
+./update-agent-context.ps1   # Updates all existing agent files
+
+.NOTES
+Relies on common helper functions in common.ps1
+#>
+param(
+    [Parameter(Position=0)]
+    [ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','junie','kilocode','auggie','roo','codebuddy','amp','shai','tabnine','kiro-cli','agy','bob','vibe','qodercli','kimi','trae','pi','iflow','forge','generic')]
+    [string]$AgentType
+)
+
+$ErrorActionPreference = 'Stop'
+
+# Import common helpers
+$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
+. (Join-Path $ScriptDir 'common.ps1')
+
+# Acquire environment paths
+$envData = Get-FeaturePathsEnv
+$REPO_ROOT     = $envData.REPO_ROOT
+$CURRENT_BRANCH = $envData.CURRENT_BRANCH
+$HAS_GIT       = $envData.HAS_GIT
+$IMPL_PLAN     = $envData.IMPL_PLAN
+$NEW_PLAN = $IMPL_PLAN
+
+# Agent file paths
+$CLAUDE_FILE   = Join-Path $REPO_ROOT 'CLAUDE.md'
+$GEMINI_FILE   = Join-Path $REPO_ROOT 'GEMINI.md'
+$COPILOT_FILE  = Join-Path $REPO_ROOT '.github/copilot-instructions.md'
+$CURSOR_FILE   = Join-Path $REPO_ROOT '.cursor/rules/specify-rules.mdc'
+$QWEN_FILE     = Join-Path $REPO_ROOT 'QWEN.md'
+$AGENTS_FILE   = Join-Path $REPO_ROOT 'AGENTS.md'
+$WINDSURF_FILE = Join-Path $REPO_ROOT '.windsurf/rules/specify-rules.md'
+$JUNIE_FILE = Join-Path $REPO_ROOT '.junie/AGENTS.md'
+$KILOCODE_FILE = Join-Path $REPO_ROOT '.kilocode/rules/specify-rules.md'
+$AUGGIE_FILE   = Join-Path $REPO_ROOT '.augment/rules/specify-rules.md'
+$ROO_FILE      = Join-Path $REPO_ROOT '.roo/rules/specify-rules.md'
+$CODEBUDDY_FILE = Join-Path $REPO_ROOT 'CODEBUDDY.md'
+$QODER_FILE    = Join-Path $REPO_ROOT 'QODER.md'
+$AMP_FILE      = Join-Path $REPO_ROOT 'AGENTS.md'
+$SHAI_FILE     = Join-Path $REPO_ROOT 'SHAI.md'
+$TABNINE_FILE  = Join-Path $REPO_ROOT 'TABNINE.md'
+$KIRO_FILE     = Join-Path $REPO_ROOT 'AGENTS.md'
+$AGY_FILE      = Join-Path $REPO_ROOT '.agent/rules/specify-rules.md'
+$BOB_FILE      = Join-Path $REPO_ROOT 'AGENTS.md'
+$VIBE_FILE     = Join-Path $REPO_ROOT '.vibe/agents/specify-agents.md'
+$KIMI_FILE     = Join-Path $REPO_ROOT 'KIMI.md'
+$TRAE_FILE     = Join-Path $REPO_ROOT '.trae/rules/AGENTS.md'
+$IFLOW_FILE    = Join-Path $REPO_ROOT 'IFLOW.md'
+$FORGE_FILE    = Join-Path $REPO_ROOT 'AGENTS.md'
+
+$TEMPLATE_FILE = Join-Path $REPO_ROOT '.specify/templates/agent-file-template.md'
+
+# Parsed plan data placeholders
+$script:NEW_LANG = ''
+$script:NEW_FRAMEWORK = ''
+$script:NEW_DB = ''
+$script:NEW_PROJECT_TYPE = ''
+
+function Write-Info { 
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$Message
+    )
+    Write-Host "INFO: $Message" 
+}
+
+function Write-Success { 
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$Message
+    )
+    Write-Host "$([char]0x2713) $Message" 
+}
+
+function Write-WarningMsg { 
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$Message
+    )
+    Write-Warning $Message 
+}
+
+function Write-Err { 
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$Message
+    )
+    Write-Host "ERROR: $Message" -ForegroundColor Red 
+}
+
+function Validate-Environment {
+    if (-not $CURRENT_BRANCH) {
+        Write-Err 'Unable to determine current feature'
+        if ($HAS_GIT) { Write-Info "Make sure you're on a feature branch" } else { Write-Info 'Set SPECIFY_FEATURE environment variable or create a feature first' }
+        exit 1
+    }
+    if (-not (Test-Path $NEW_PLAN)) {
+        Write-Err "No plan.md found at $NEW_PLAN"
+        Write-Info 'Ensure you are working on a feature with a corresponding spec directory'
+        if (-not $HAS_GIT) { Write-Info 'Use: $env:SPECIFY_FEATURE=your-feature-name or create a new feature first' }
+        exit 1
+    }
+    if (-not (Test-Path $TEMPLATE_FILE)) {
+        Write-Err "Template file not found at $TEMPLATE_FILE"
+        Write-Info 'Run specify init to scaffold .specify/templates, or add agent-file-template.md there.'
+        exit 1
+    }
+}
+
+function Extract-PlanField {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$FieldPattern,
+        [Parameter(Mandatory=$true)]
+        [string]$PlanFile
+    )
+    if (-not (Test-Path $PlanFile)) { return '' }
+    # Lines like **Language/Version**: Python 3.12
+    $regex = "^\*\*$([Regex]::Escape($FieldPattern))\*\*: (.+)$"
+    Get-Content -LiteralPath $PlanFile -Encoding utf8 | ForEach-Object {
+        if ($_ -match $regex) { 
+            $val = $Matches[1].Trim()
+            if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val }
+        }
+    } | Select-Object -First 1
+}
+
+function Parse-PlanData {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$PlanFile
+    )
+    if (-not (Test-Path $PlanFile)) { Write-Err "Plan file not found: $PlanFile"; return $false }
+    Write-Info "Parsing plan data from $PlanFile"
+    $script:NEW_LANG        = Extract-PlanField -FieldPattern 'Language/Version' -PlanFile $PlanFile
+    $script:NEW_FRAMEWORK   = Extract-PlanField -FieldPattern 'Primary Dependencies' -PlanFile $PlanFile
+    $script:NEW_DB          = Extract-PlanField -FieldPattern 'Storage' -PlanFile $PlanFile
+    $script:NEW_PROJECT_TYPE = Extract-PlanField -FieldPattern 'Project Type' -PlanFile $PlanFile
+
+    if ($NEW_LANG) { Write-Info "Found language: $NEW_LANG" } else { Write-WarningMsg 'No language information found in plan' }
+    if ($NEW_FRAMEWORK) { Write-Info "Found framework: $NEW_FRAMEWORK" }
+    if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Info "Found database: $NEW_DB" }
+    if ($NEW_PROJECT_TYPE) { Write-Info "Found project type: $NEW_PROJECT_TYPE" }
+    return $true
+}
+
+function Format-TechnologyStack {
+    param(
+        [Parameter(Mandatory=$false)]
+        [string]$Lang,
+        [Parameter(Mandatory=$false)]
+        [string]$Framework
+    )
+    $parts = @()
+    if ($Lang -and $Lang -ne 'NEEDS CLARIFICATION') { $parts += $Lang }
+    if ($Framework -and $Framework -notin @('NEEDS CLARIFICATION','N/A')) { $parts += $Framework }
+    if (-not $parts) { return '' }
+    return ($parts -join ' + ')
+}
+
+function Get-ProjectStructure { 
+    param(
+        [Parameter(Mandatory=$false)]
+        [string]$ProjectType
+    )
+    if ($ProjectType -match 'web') { return "backend/`nfrontend/`ntests/" } else { return "src/`ntests/" } 
+}
+
+function Get-CommandsForLanguage { 
+    param(
+        [Parameter(Mandatory=$false)]
+        [string]$Lang
+    )
+    switch -Regex ($Lang) {
+        'Python' { return "cd src; pytest; ruff check ." }
+        'Rust' { return "cargo test; cargo clippy" }
+        'JavaScript|TypeScript' { return "npm test; npm run lint" }
+        default { return "# Add commands for $Lang" }
+    }
+}
+
+function Get-LanguageConventions { 
+    param(
+        [Parameter(Mandatory=$false)]
+        [string]$Lang
+    )
+    if ($Lang) { "${Lang}: Follow standard conventions" } else { 'General: Follow standard conventions' } 
+}
+
+function New-AgentFile {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$TargetFile,
+        [Parameter(Mandatory=$true)]
+        [string]$ProjectName,
+        [Parameter(Mandatory=$true)]
+        [datetime]$Date
+    )
+    if (-not (Test-Path $TEMPLATE_FILE)) { Write-Err "Template not found at $TEMPLATE_FILE"; return $false }
+    $temp = New-TemporaryFile
+    Copy-Item -LiteralPath $TEMPLATE_FILE -Destination $temp -Force
+
+    $projectStructure = Get-ProjectStructure -ProjectType $NEW_PROJECT_TYPE
+    $commands = Get-CommandsForLanguage -Lang $NEW_LANG
+    $languageConventions = Get-LanguageConventions -Lang $NEW_LANG
+
+    $escaped_lang = $NEW_LANG
+    $escaped_framework = $NEW_FRAMEWORK
+    $escaped_branch = $CURRENT_BRANCH
+
+    $content = Get-Content -LiteralPath $temp -Raw -Encoding utf8
+    $content = $content -replace '\[PROJECT NAME\]',$ProjectName
+    $content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd')
+    
+    # Build the technology stack string safely
+    $techStackForTemplate = ""
+    if ($escaped_lang -and $escaped_framework) {
+        $techStackForTemplate = "- $escaped_lang + $escaped_framework ($escaped_branch)"
+    } elseif ($escaped_lang) {
+        $techStackForTemplate = "- $escaped_lang ($escaped_branch)"
+    } elseif ($escaped_framework) {
+        $techStackForTemplate = "- $escaped_framework ($escaped_branch)"
+    }
+    
+    $content = $content -replace '\[EXTRACTED FROM ALL PLAN.MD FILES\]',$techStackForTemplate
+    # For project structure we manually embed (keep newlines)
+    $escapedStructure = [Regex]::Escape($projectStructure)
+    $content = $content -replace '\[ACTUAL STRUCTURE FROM PLANS\]',$escapedStructure
+    # Replace escaped newlines placeholder after all replacements
+    $content = $content -replace '\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]',$commands
+    $content = $content -replace '\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]',$languageConventions
+    
+    # Build the recent changes string safely
+    $recentChangesForTemplate = ""
+    if ($escaped_lang -and $escaped_framework) {
+        $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang} + ${escaped_framework}"
+    } elseif ($escaped_lang) {
+        $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang}"
+    } elseif ($escaped_framework) {
+        $recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_framework}"
+    }
+    
+    $content = $content -replace '\[LAST 3 FEATURES AND WHAT THEY ADDED\]',$recentChangesForTemplate
+    # Convert literal \n sequences introduced by Escape to real newlines
+    $content = $content -replace '\\n',[Environment]::NewLine
+
+    # Prepend Cursor frontmatter for .mdc files so rules are auto-included
+    if ($TargetFile -match '\.mdc$') {
+        $frontmatter = @('---','description: Project Development Guidelines','globs: ["**/*"]','alwaysApply: true','---','') -join [Environment]::NewLine
+        $content = $frontmatter + $content
+    }
+
+    $parent = Split-Path -Parent $TargetFile
+    if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
+    Set-Content -LiteralPath $TargetFile -Value $content -NoNewline -Encoding utf8
+    Remove-Item $temp -Force
+    return $true
+}
+
+function Update-ExistingAgentFile {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$TargetFile,
+        [Parameter(Mandatory=$true)]
+        [datetime]$Date
+    )
+    if (-not (Test-Path $TargetFile)) { return (New-AgentFile -TargetFile $TargetFile -ProjectName (Split-Path $REPO_ROOT -Leaf) -Date $Date) }
+
+    $techStack = Format-TechnologyStack -Lang $NEW_LANG -Framework $NEW_FRAMEWORK
+    $newTechEntries = @()
+    if ($techStack) {
+        $escapedTechStack = [Regex]::Escape($techStack)
+        if (-not (Select-String -Pattern $escapedTechStack -Path $TargetFile -Quiet)) { 
+            $newTechEntries += "- $techStack ($CURRENT_BRANCH)" 
+        }
+    }
+    if ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) {
+        $escapedDB = [Regex]::Escape($NEW_DB)
+        if (-not (Select-String -Pattern $escapedDB -Path $TargetFile -Quiet)) { 
+            $newTechEntries += "- $NEW_DB ($CURRENT_BRANCH)" 
+        }
+    }
+    $newChangeEntry = ''
+    if ($techStack) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${techStack}" }
+    elseif ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${NEW_DB}" }
+
+    $lines = Get-Content -LiteralPath $TargetFile -Encoding utf8
+    $output = New-Object System.Collections.Generic.List[string]
+    $inTech = $false; $inChanges = $false; $techAdded = $false; $changeAdded = $false; $existingChanges = 0
+
+    for ($i=0; $i -lt $lines.Count; $i++) {
+        $line = $lines[$i]
+        if ($line -eq '## Active Technologies') {
+            $output.Add($line)
+            $inTech = $true
+            continue
+        }
+        if ($inTech -and $line -match '^##\s') {
+            if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
+            $output.Add($line); $inTech = $false; continue
+        }
+        if ($inTech -and [string]::IsNullOrWhiteSpace($line)) {
+            if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
+            $output.Add($line); continue
+        }
+        if ($line -eq '## Recent Changes') {
+            $output.Add($line)
+            if ($newChangeEntry) { $output.Add($newChangeEntry); $changeAdded = $true }
+            $inChanges = $true
+            continue
+        }
+        if ($inChanges -and $line -match '^##\s') { $output.Add($line); $inChanges = $false; continue }
+        if ($inChanges -and $line -match '^- ') {
+            if ($existingChanges -lt 2) { $output.Add($line); $existingChanges++ }
+            continue
+        }
+        if ($line -match '(\*\*)?Last updated(\*\*)?: .*\d{4}-\d{2}-\d{2}') {
+            $output.Add(($line -replace '\d{4}-\d{2}-\d{2}',$Date.ToString('yyyy-MM-dd')))
+            continue
+        }
+        $output.Add($line)
+    }
+
+    # Post-loop check: if we're still in the Active Technologies section and haven't added new entries
+    if ($inTech -and -not $techAdded -and $newTechEntries.Count -gt 0) {
+        $newTechEntries | ForEach-Object { $output.Add($_) }
+    }
+
+    # Ensure Cursor .mdc files have YAML frontmatter for auto-inclusion
+    if ($TargetFile -match '\.mdc$' -and $output.Count -gt 0 -and $output[0] -ne '---') {
+        $frontmatter = @('---','description: Project Development Guidelines','globs: ["**/*"]','alwaysApply: true','---','')
+        $output.InsertRange(0, $frontmatter)
+    }
+
+    Set-Content -LiteralPath $TargetFile -Value ($output -join [Environment]::NewLine) -Encoding utf8
+    return $true
+}
+
+function Update-AgentFile {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$TargetFile,
+        [Parameter(Mandatory=$true)]
+        [string]$AgentName
+    )
+    if (-not $TargetFile -or -not $AgentName) { Write-Err 'Update-AgentFile requires TargetFile and AgentName'; return $false }
+    Write-Info "Updating $AgentName context file: $TargetFile"
+    $projectName = Split-Path $REPO_ROOT -Leaf
+    $date = Get-Date
+
+    $dir = Split-Path -Parent $TargetFile
+    if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
+
+    if (-not (Test-Path $TargetFile)) {
+        if (New-AgentFile -TargetFile $TargetFile -ProjectName $projectName -Date $date) { Write-Success "Created new $AgentName context file" } else { Write-Err 'Failed to create new agent file'; return $false }
+    } else {
+        try {
+            if (Update-ExistingAgentFile -TargetFile $TargetFile -Date $date) { Write-Success "Updated existing $AgentName context file" } else { Write-Err 'Failed to update agent file'; return $false }
+        } catch {
+            Write-Err "Cannot access or update existing file: $TargetFile. $_"
+            return $false
+        }
+    }
+    return $true
+}
+
+function Update-SpecificAgent {
+    param(
+        [Parameter(Mandatory=$true)]
+        [string]$Type
+    )
+    switch ($Type) {
+        'claude'   { Update-AgentFile -TargetFile $CLAUDE_FILE   -AgentName 'Claude Code' }
+        'gemini'   { Update-AgentFile -TargetFile $GEMINI_FILE   -AgentName 'Gemini CLI' }
+        'copilot'  { Update-AgentFile -TargetFile $COPILOT_FILE  -AgentName 'GitHub Copilot' }
+        'cursor-agent' { Update-AgentFile -TargetFile $CURSOR_FILE   -AgentName 'Cursor IDE' }
+        'qwen'     { Update-AgentFile -TargetFile $QWEN_FILE     -AgentName 'Qwen Code' }
+        'opencode' { Update-AgentFile -TargetFile $AGENTS_FILE   -AgentName 'opencode' }
+        'codex'    { Update-AgentFile -TargetFile $AGENTS_FILE   -AgentName 'Codex CLI' }
+        'windsurf' { Update-AgentFile -TargetFile $WINDSURF_FILE -AgentName 'Windsurf' }
+        'junie'    { Update-AgentFile -TargetFile $JUNIE_FILE    -AgentName 'Junie' }
+        'kilocode' { Update-AgentFile -TargetFile $KILOCODE_FILE -AgentName 'Kilo Code' }
+        'auggie'   { Update-AgentFile -TargetFile $AUGGIE_FILE   -AgentName 'Auggie CLI' }
+        'roo'      { Update-AgentFile -TargetFile $ROO_FILE      -AgentName 'Roo Code' }
+        'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI' }
+        'qodercli' { Update-AgentFile -TargetFile $QODER_FILE    -AgentName 'Qoder CLI' }
+        'amp'      { Update-AgentFile -TargetFile $AMP_FILE      -AgentName 'Amp' }
+        'shai'     { Update-AgentFile -TargetFile $SHAI_FILE     -AgentName 'SHAI' }
+        'tabnine'  { Update-AgentFile -TargetFile $TABNINE_FILE  -AgentName 'Tabnine CLI' }
+        'kiro-cli' { Update-AgentFile -TargetFile $KIRO_FILE     -AgentName 'Kiro CLI' }
+        'agy'      { Update-AgentFile -TargetFile $AGY_FILE      -AgentName 'Antigravity' }
+        'bob'      { Update-AgentFile -TargetFile $BOB_FILE      -AgentName 'IBM Bob' }
+        'vibe'     { Update-AgentFile -TargetFile $VIBE_FILE     -AgentName 'Mistral Vibe' }
+        'kimi'     { Update-AgentFile -TargetFile $KIMI_FILE     -AgentName 'Kimi Code' }
+        'trae'     { Update-AgentFile -TargetFile $TRAE_FILE     -AgentName 'Trae' }
+        'pi'       { Update-AgentFile -TargetFile $AGENTS_FILE   -AgentName 'Pi Coding Agent' }
+        'iflow'    { Update-AgentFile -TargetFile $IFLOW_FILE    -AgentName 'iFlow CLI' }
+        'forge'    { Update-AgentFile -TargetFile $FORGE_FILE    -AgentName 'Forge' }
+        'generic'  { Write-Info 'Generic agent: no predefined context file. Use the agent-specific update script for your agent.' }
+        default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|junie|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|trae|pi|iflow|forge|generic'; return $false }
+    }
+}
+
+function Update-AllExistingAgents {
+    $found = $false
+    $ok = $true
+    $updatedPaths = @()
+    
+    # Helper function to update only if file exists and hasn't been updated yet
+    function Update-IfNew {
+        param(
+            [Parameter(Mandatory=$true)]
+            [string]$FilePath,
+            [Parameter(Mandatory=$true)]
+            [string]$AgentName
+        )
+        
+        if (-not (Test-Path $FilePath)) { return $true }
+        
+        # Get the real path to detect duplicates (e.g., AMP_FILE, KIRO_FILE, BOB_FILE all point to AGENTS.md)
+        $realPath = (Get-Item -LiteralPath $FilePath).FullName
+        
+        # Check if we've already updated this file
+        if ($updatedPaths -contains $realPath) {
+            return $true
+        }
+        
+        # Record the file as seen before attempting the update
+        # Use parent scope (1) to modify Update-AllExistingAgents' local variables
+        Set-Variable -Name updatedPaths -Value ($updatedPaths + $realPath) -Scope 1
+        Set-Variable -Name found -Value $true -Scope 1
+        
+        # Perform the update
+        return (Update-AgentFile -TargetFile $FilePath -AgentName $AgentName)
+    }
+    
+    if (-not (Update-IfNew -FilePath $CLAUDE_FILE   -AgentName 'Claude Code')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $GEMINI_FILE   -AgentName 'Gemini CLI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $COPILOT_FILE  -AgentName 'GitHub Copilot')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $CURSOR_FILE   -AgentName 'Cursor IDE')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $QWEN_FILE     -AgentName 'Qwen Code')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $AGENTS_FILE   -AgentName 'Codex/opencode/Amp/Kiro/Bob/Pi/Forge')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $WINDSURF_FILE -AgentName 'Windsurf')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $JUNIE_FILE    -AgentName 'Junie')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $KILOCODE_FILE -AgentName 'Kilo Code')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $AUGGIE_FILE   -AgentName 'Auggie CLI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $ROO_FILE      -AgentName 'Roo Code')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $QODER_FILE    -AgentName 'Qoder CLI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $SHAI_FILE     -AgentName 'SHAI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $TABNINE_FILE  -AgentName 'Tabnine CLI')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $AGY_FILE      -AgentName 'Antigravity')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $VIBE_FILE     -AgentName 'Mistral Vibe')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $KIMI_FILE     -AgentName 'Kimi Code')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $TRAE_FILE     -AgentName 'Trae')) { $ok = $false }
+    if (-not (Update-IfNew -FilePath $IFLOW_FILE    -AgentName 'iFlow CLI')) { $ok = $false }
+    
+    if (-not $found) {
+        Write-Info 'No existing agent files found, creating default Claude file...'
+        if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }
+    }
+    return $ok
+}
+
+function Print-Summary {
+    Write-Host ''
+    Write-Info 'Summary of changes:'
+    if ($NEW_LANG) { Write-Host "  - Added language: $NEW_LANG" }
+    if ($NEW_FRAMEWORK) { Write-Host "  - Added framework: $NEW_FRAMEWORK" }
+    if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host "  - Added database: $NEW_DB" }
+    Write-Host ''
+    Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|junie|kilocode|auggie|roo|codebuddy|amp|shai|tabnine|kiro-cli|agy|bob|vibe|qodercli|kimi|trae|pi|iflow|forge|generic]'
+}
+
+function Main {
+    Validate-Environment
+    Write-Info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
+    if (-not (Parse-PlanData -PlanFile $NEW_PLAN)) { Write-Err 'Failed to parse plan data'; exit 1 }
+    $success = $true
+    if ($AgentType) {
+        Write-Info "Updating specific agent: $AgentType"
+        if (-not (Update-SpecificAgent -Type $AgentType)) { $success = $false }
+    }
+    else {
+        Write-Info 'No agent specified, updating all existing agent files...'
+        if (-not (Update-AllExistingAgents)) { $success = $false }
+    }
+    Print-Summary
+    if ($success) { Write-Success 'Agent context update completed successfully'; exit 0 } else { Write-Err 'Agent context update completed with errors'; exit 1 }
+}
+
+Main

+ 28 - 0
.specify/templates/agent-file-template.md

@@ -0,0 +1,28 @@
+# [PROJECT NAME] Development Guidelines
+
+Auto-generated from all feature plans. Last updated: [DATE]
+
+## Active Technologies
+
+[EXTRACTED FROM ALL PLAN.MD FILES]
+
+## Project Structure
+
+```text
+[ACTUAL STRUCTURE FROM PLANS]
+```
+
+## Commands
+
+[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]
+
+## Code Style
+
+[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]
+
+## Recent Changes
+
+[LAST 3 FEATURES AND WHAT THEY ADDED]
+
+<!-- MANUAL ADDITIONS START -->
+<!-- MANUAL ADDITIONS END -->

+ 40 - 0
.specify/templates/checklist-template.md

@@ -0,0 +1,40 @@
+# [CHECKLIST TYPE] Checklist: [FEATURE NAME]
+
+**Purpose**: [Brief description of what this checklist covers]
+**Created**: [DATE]
+**Feature**: [Link to spec.md or relevant documentation]
+
+**Note**: This checklist is generated by the `/speckit.checklist` command based on feature context and requirements.
+
+<!-- 
+  ============================================================================
+  IMPORTANT: The checklist items below are SAMPLE ITEMS for illustration only.
+  
+  The /speckit.checklist command MUST replace these with actual items based on:
+  - User's specific checklist request
+  - Feature requirements from spec.md
+  - Technical context from plan.md
+  - Implementation details from tasks.md
+  
+  DO NOT keep these sample items in the generated checklist file.
+  ============================================================================
+-->
+
+## [Category 1]
+
+- [ ] CHK001 First checklist item with clear action
+- [ ] CHK002 Second checklist item
+- [ ] CHK003 Third checklist item
+
+## [Category 2]
+
+- [ ] CHK004 Another category item
+- [ ] CHK005 Item with specific criteria
+- [ ] CHK006 Final item in this category
+
+## Notes
+
+- Check items off as completed: `[x]`
+- Add comments or findings inline
+- Link to relevant resources or documentation
+- Items are numbered sequentially for easy reference

+ 50 - 0
.specify/templates/constitution-template.md

@@ -0,0 +1,50 @@
+# [PROJECT_NAME] Constitution
+<!-- Example: Spec Constitution, TaskFlow Constitution, etc. -->
+
+## Core Principles
+
+### [PRINCIPLE_1_NAME]
+<!-- Example: I. Library-First -->
+[PRINCIPLE_1_DESCRIPTION]
+<!-- Example: Every feature starts as a standalone library; Libraries must be self-contained, independently testable, documented; Clear purpose required - no organizational-only libraries -->
+
+### [PRINCIPLE_2_NAME]
+<!-- Example: II. CLI Interface -->
+[PRINCIPLE_2_DESCRIPTION]
+<!-- Example: Every library exposes functionality via CLI; Text in/out protocol: stdin/args → stdout, errors → stderr; Support JSON + human-readable formats -->
+
+### [PRINCIPLE_3_NAME]
+<!-- Example: III. Test-First (NON-NEGOTIABLE) -->
+[PRINCIPLE_3_DESCRIPTION]
+<!-- Example: TDD mandatory: Tests written → User approved → Tests fail → Then implement; Red-Green-Refactor cycle strictly enforced -->
+
+### [PRINCIPLE_4_NAME]
+<!-- Example: IV. Integration Testing -->
+[PRINCIPLE_4_DESCRIPTION]
+<!-- Example: Focus areas requiring integration tests: New library contract tests, Contract changes, Inter-service communication, Shared schemas -->
+
+### [PRINCIPLE_5_NAME]
+<!-- Example: V. Observability, VI. Versioning & Breaking Changes, VII. Simplicity -->
+[PRINCIPLE_5_DESCRIPTION]
+<!-- Example: Text I/O ensures debuggability; Structured logging required; Or: MAJOR.MINOR.BUILD format; Or: Start simple, YAGNI principles -->
+
+## [SECTION_2_NAME]
+<!-- Example: Additional Constraints, Security Requirements, Performance Standards, etc. -->
+
+[SECTION_2_CONTENT]
+<!-- Example: Technology stack requirements, compliance standards, deployment policies, etc. -->
+
+## [SECTION_3_NAME]
+<!-- Example: Development Workflow, Review Process, Quality Gates, etc. -->
+
+[SECTION_3_CONTENT]
+<!-- Example: Code review requirements, testing gates, deployment approval process, etc. -->
+
+## Governance
+<!-- Example: Constitution supersedes all other practices; Amendments require documentation, approval, migration plan -->
+
+[GOVERNANCE_RULES]
+<!-- Example: All PRs/reviews must verify compliance; Complexity must be justified; Use [GUIDANCE_FILE] for runtime development guidance -->
+
+**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE]
+<!-- Example: Version: 2.1.1 | Ratified: 2025-06-13 | Last Amended: 2025-07-16 -->

+ 104 - 0
.specify/templates/plan-template.md

@@ -0,0 +1,104 @@
+# Implementation Plan: [FEATURE]
+
+**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
+**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
+
+**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/plan-template.md` for the execution workflow.
+
+## Summary
+
+[Extract from feature spec: primary requirement + technical approach from research]
+
+## Technical Context
+
+<!--
+  ACTION REQUIRED: Replace the content in this section with the technical details
+  for the project. The structure here is presented in advisory capacity to guide
+  the iteration process.
+-->
+
+**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]  
+**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]  
+**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]  
+**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]  
+**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
+**Project Type**: [e.g., library/cli/web-service/mobile-app/compiler/desktop-app or NEEDS CLARIFICATION]  
+**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]  
+**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]  
+**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
+
+## Constitution Check
+
+*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
+
+[Gates determined based on constitution file]
+
+## Project Structure
+
+### Documentation (this feature)
+
+```text
+specs/[###-feature]/
+├── plan.md              # This file (/speckit.plan command output)
+├── research.md          # Phase 0 output (/speckit.plan command)
+├── data-model.md        # Phase 1 output (/speckit.plan command)
+├── quickstart.md        # Phase 1 output (/speckit.plan command)
+├── contracts/           # Phase 1 output (/speckit.plan command)
+└── tasks.md             # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
+```
+
+### Source Code (repository root)
+<!--
+  ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
+  for this feature. Delete unused options and expand the chosen structure with
+  real paths (e.g., apps/admin, packages/something). The delivered plan must
+  not include Option labels.
+-->
+
+```text
+# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
+src/
+├── models/
+├── services/
+├── cli/
+└── lib/
+
+tests/
+├── contract/
+├── integration/
+└── unit/
+
+# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
+backend/
+├── src/
+│   ├── models/
+│   ├── services/
+│   └── api/
+└── tests/
+
+frontend/
+├── src/
+│   ├── components/
+│   ├── pages/
+│   └── services/
+└── tests/
+
+# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
+api/
+└── [same as backend above]
+
+ios/ or android/
+└── [platform-specific structure: feature modules, UI flows, platform tests]
+```
+
+**Structure Decision**: [Document the selected structure and reference the real
+directories captured above]
+
+## Complexity Tracking
+
+> **Fill ONLY if Constitution Check has violations that must be justified**
+
+| Violation | Why Needed | Simpler Alternative Rejected Because |
+|-----------|------------|-------------------------------------|
+| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
+| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |

+ 128 - 0
.specify/templates/spec-template.md

@@ -0,0 +1,128 @@
+# Feature Specification: [FEATURE NAME]
+
+**Feature Branch**: `[###-feature-name]`  
+**Created**: [DATE]  
+**Status**: Draft  
+**Input**: User description: "$ARGUMENTS"
+
+## User Scenarios & Testing *(mandatory)*
+
+<!--
+  IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
+  Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
+  you should still have a viable MVP (Minimum Viable Product) that delivers value.
+  
+  Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
+  Think of each story as a standalone slice of functionality that can be:
+  - Developed independently
+  - Tested independently
+  - Deployed independently
+  - Demonstrated to users independently
+-->
+
+### User Story 1 - [Brief Title] (Priority: P1)
+
+[Describe this user journey in plain language]
+
+**Why this priority**: [Explain the value and why it has this priority level]
+
+**Independent Test**: [Describe how this can be tested independently - e.g., "Can be fully tested by [specific action] and delivers [specific value]"]
+
+**Acceptance Scenarios**:
+
+1. **Given** [initial state], **When** [action], **Then** [expected outcome]
+2. **Given** [initial state], **When** [action], **Then** [expected outcome]
+
+---
+
+### User Story 2 - [Brief Title] (Priority: P2)
+
+[Describe this user journey in plain language]
+
+**Why this priority**: [Explain the value and why it has this priority level]
+
+**Independent Test**: [Describe how this can be tested independently]
+
+**Acceptance Scenarios**:
+
+1. **Given** [initial state], **When** [action], **Then** [expected outcome]
+
+---
+
+### User Story 3 - [Brief Title] (Priority: P3)
+
+[Describe this user journey in plain language]
+
+**Why this priority**: [Explain the value and why it has this priority level]
+
+**Independent Test**: [Describe how this can be tested independently]
+
+**Acceptance Scenarios**:
+
+1. **Given** [initial state], **When** [action], **Then** [expected outcome]
+
+---
+
+[Add more user stories as needed, each with an assigned priority]
+
+### Edge Cases
+
+<!--
+  ACTION REQUIRED: The content in this section represents placeholders.
+  Fill them out with the right edge cases.
+-->
+
+- What happens when [boundary condition]?
+- How does system handle [error scenario]?
+
+## Requirements *(mandatory)*
+
+<!--
+  ACTION REQUIRED: The content in this section represents placeholders.
+  Fill them out with the right functional requirements.
+-->
+
+### Functional Requirements
+
+- **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"]
+- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"]  
+- **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"]
+- **FR-004**: System MUST [data requirement, e.g., "persist user preferences"]
+- **FR-005**: System MUST [behavior, e.g., "log all security events"]
+
+*Example of marking unclear requirements:*
+
+- **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?]
+- **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified]
+
+### Key Entities *(include if feature involves data)*
+
+- **[Entity 1]**: [What it represents, key attributes without implementation]
+- **[Entity 2]**: [What it represents, relationships to other entities]
+
+## Success Criteria *(mandatory)*
+
+<!--
+  ACTION REQUIRED: Define measurable success criteria.
+  These must be technology-agnostic and measurable.
+-->
+
+### Measurable Outcomes
+
+- **SC-001**: [Measurable metric, e.g., "Users can complete account creation in under 2 minutes"]
+- **SC-002**: [Measurable metric, e.g., "System handles 1000 concurrent users without degradation"]
+- **SC-003**: [User satisfaction metric, e.g., "90% of users successfully complete primary task on first attempt"]
+- **SC-004**: [Business metric, e.g., "Reduce support tickets related to [X] by 50%"]
+
+## Assumptions
+
+<!--
+  ACTION REQUIRED: The content in this section represents placeholders.
+  Fill them out with the right assumptions based on reasonable defaults
+  chosen when the feature description did not specify certain details.
+-->
+
+- [Assumption about target users, e.g., "Users have stable internet connectivity"]
+- [Assumption about scope boundaries, e.g., "Mobile support is out of scope for v1"]
+- [Assumption about data/environment, e.g., "Existing authentication system will be reused"]
+- [Dependency on existing system/service, e.g., "Requires access to the existing user profile API"]

+ 251 - 0
.specify/templates/tasks-template.md

@@ -0,0 +1,251 @@
+---
+
+description: "Task list template for feature implementation"
+---
+
+# Tasks: [FEATURE NAME]
+
+**Input**: Design documents from `/specs/[###-feature-name]/`
+**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
+
+**Tests**: The examples below include test tasks. Tests are OPTIONAL - only include them if explicitly requested in the feature specification.
+
+**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
+
+## Format: `[ID] [P?] [Story] Description`
+
+- **[P]**: Can run in parallel (different files, no dependencies)
+- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
+- Include exact file paths in descriptions
+
+## Path Conventions
+
+- **Single project**: `src/`, `tests/` at repository root
+- **Web app**: `backend/src/`, `frontend/src/`
+- **Mobile**: `api/src/`, `ios/src/` or `android/src/`
+- Paths shown below assume single project - adjust based on plan.md structure
+
+<!-- 
+  ============================================================================
+  IMPORTANT: The tasks below are SAMPLE TASKS for illustration purposes only.
+  
+  The /speckit.tasks command MUST replace these with actual tasks based on:
+  - User stories from spec.md (with their priorities P1, P2, P3...)
+  - Feature requirements from plan.md
+  - Entities from data-model.md
+  - Endpoints from contracts/
+  
+  Tasks MUST be organized by user story so each story can be:
+  - Implemented independently
+  - Tested independently
+  - Delivered as an MVP increment
+  
+  DO NOT keep these sample tasks in the generated tasks.md file.
+  ============================================================================
+-->
+
+## Phase 1: Setup (Shared Infrastructure)
+
+**Purpose**: Project initialization and basic structure
+
+- [ ] T001 Create project structure per implementation plan
+- [ ] T002 Initialize [language] project with [framework] dependencies
+- [ ] T003 [P] Configure linting and formatting tools
+
+---
+
+## Phase 2: Foundational (Blocking Prerequisites)
+
+**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
+
+**⚠️ CRITICAL**: No user story work can begin until this phase is complete
+
+Examples of foundational tasks (adjust based on your project):
+
+- [ ] T004 Setup database schema and migrations framework
+- [ ] T005 [P] Implement authentication/authorization framework
+- [ ] T006 [P] Setup API routing and middleware structure
+- [ ] T007 Create base models/entities that all stories depend on
+- [ ] T008 Configure error handling and logging infrastructure
+- [ ] T009 Setup environment configuration management
+
+**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
+
+---
+
+## Phase 3: User Story 1 - [Title] (Priority: P1) 🎯 MVP
+
+**Goal**: [Brief description of what this story delivers]
+
+**Independent Test**: [How to verify this story works on its own]
+
+### Tests for User Story 1 (OPTIONAL - only if tests requested) ⚠️
+
+> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
+
+- [ ] T010 [P] [US1] Contract test for [endpoint] in tests/contract/test_[name].py
+- [ ] T011 [P] [US1] Integration test for [user journey] in tests/integration/test_[name].py
+
+### Implementation for User Story 1
+
+- [ ] T012 [P] [US1] Create [Entity1] model in src/models/[entity1].py
+- [ ] T013 [P] [US1] Create [Entity2] model in src/models/[entity2].py
+- [ ] T014 [US1] Implement [Service] in src/services/[service].py (depends on T012, T013)
+- [ ] T015 [US1] Implement [endpoint/feature] in src/[location]/[file].py
+- [ ] T016 [US1] Add validation and error handling
+- [ ] T017 [US1] Add logging for user story 1 operations
+
+**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently
+
+---
+
+## Phase 4: User Story 2 - [Title] (Priority: P2)
+
+**Goal**: [Brief description of what this story delivers]
+
+**Independent Test**: [How to verify this story works on its own]
+
+### Tests for User Story 2 (OPTIONAL - only if tests requested) ⚠️
+
+- [ ] T018 [P] [US2] Contract test for [endpoint] in tests/contract/test_[name].py
+- [ ] T019 [P] [US2] Integration test for [user journey] in tests/integration/test_[name].py
+
+### Implementation for User Story 2
+
+- [ ] T020 [P] [US2] Create [Entity] model in src/models/[entity].py
+- [ ] T021 [US2] Implement [Service] in src/services/[service].py
+- [ ] T022 [US2] Implement [endpoint/feature] in src/[location]/[file].py
+- [ ] T023 [US2] Integrate with User Story 1 components (if needed)
+
+**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently
+
+---
+
+## Phase 5: User Story 3 - [Title] (Priority: P3)
+
+**Goal**: [Brief description of what this story delivers]
+
+**Independent Test**: [How to verify this story works on its own]
+
+### Tests for User Story 3 (OPTIONAL - only if tests requested) ⚠️
+
+- [ ] T024 [P] [US3] Contract test for [endpoint] in tests/contract/test_[name].py
+- [ ] T025 [P] [US3] Integration test for [user journey] in tests/integration/test_[name].py
+
+### Implementation for User Story 3
+
+- [ ] T026 [P] [US3] Create [Entity] model in src/models/[entity].py
+- [ ] T027 [US3] Implement [Service] in src/services/[service].py
+- [ ] T028 [US3] Implement [endpoint/feature] in src/[location]/[file].py
+
+**Checkpoint**: All user stories should now be independently functional
+
+---
+
+[Add more user story phases as needed, following the same pattern]
+
+---
+
+## Phase N: Polish & Cross-Cutting Concerns
+
+**Purpose**: Improvements that affect multiple user stories
+
+- [ ] TXXX [P] Documentation updates in docs/
+- [ ] TXXX Code cleanup and refactoring
+- [ ] TXXX Performance optimization across all stories
+- [ ] TXXX [P] Additional unit tests (if requested) in tests/unit/
+- [ ] TXXX Security hardening
+- [ ] TXXX Run quickstart.md validation
+
+---
+
+## Dependencies & Execution Order
+
+### Phase Dependencies
+
+- **Setup (Phase 1)**: No dependencies - can start immediately
+- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories
+- **User Stories (Phase 3+)**: All depend on Foundational phase completion
+  - User stories can then proceed in parallel (if staffed)
+  - Or sequentially in priority order (P1 → P2 → P3)
+- **Polish (Final Phase)**: Depends on all desired user stories being complete
+
+### User Story Dependencies
+
+- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories
+- **User Story 2 (P2)**: Can start after Foundational (Phase 2) - May integrate with US1 but should be independently testable
+- **User Story 3 (P3)**: Can start after Foundational (Phase 2) - May integrate with US1/US2 but should be independently testable
+
+### Within Each User Story
+
+- Tests (if included) MUST be written and FAIL before implementation
+- Models before services
+- Services before endpoints
+- Core implementation before integration
+- Story complete before moving to next priority
+
+### Parallel Opportunities
+
+- All Setup tasks marked [P] can run in parallel
+- All Foundational tasks marked [P] can run in parallel (within Phase 2)
+- Once Foundational phase completes, all user stories can start in parallel (if team capacity allows)
+- All tests for a user story marked [P] can run in parallel
+- Models within a story marked [P] can run in parallel
+- Different user stories can be worked on in parallel by different team members
+
+---
+
+## Parallel Example: User Story 1
+
+```bash
+# Launch all tests for User Story 1 together (if tests requested):
+Task: "Contract test for [endpoint] in tests/contract/test_[name].py"
+Task: "Integration test for [user journey] in tests/integration/test_[name].py"
+
+# Launch all models for User Story 1 together:
+Task: "Create [Entity1] model in src/models/[entity1].py"
+Task: "Create [Entity2] model in src/models/[entity2].py"
+```
+
+---
+
+## Implementation Strategy
+
+### MVP First (User Story 1 Only)
+
+1. Complete Phase 1: Setup
+2. Complete Phase 2: Foundational (CRITICAL - blocks all stories)
+3. Complete Phase 3: User Story 1
+4. **STOP and VALIDATE**: Test User Story 1 independently
+5. Deploy/demo if ready
+
+### Incremental Delivery
+
+1. Complete Setup + Foundational → Foundation ready
+2. Add User Story 1 → Test independently → Deploy/Demo (MVP!)
+3. Add User Story 2 → Test independently → Deploy/Demo
+4. Add User Story 3 → Test independently → Deploy/Demo
+5. Each story adds value without breaking previous stories
+
+### Parallel Team Strategy
+
+With multiple developers:
+
+1. Team completes Setup + Foundational together
+2. Once Foundational is done:
+   - Developer A: User Story 1
+   - Developer B: User Story 2
+   - Developer C: User Story 3
+3. Stories complete and integrate independently
+
+---
+
+## Notes
+
+- [P] tasks = different files, no dependencies
+- [Story] label maps task to specific user story for traceability
+- Each user story should be independently completable and testable
+- Verify tests fail before implementing
+- Commit after each task or logical group
+- Stop at any checkpoint to validate story independently
+- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence

+ 30 - 0
CLAUDE.md

@@ -0,0 +1,30 @@
+# foodie_server Development Guidelines
+
+Auto-generated from all feature plans. Last updated: 2026-04-29
+
+## Active Technologies
+
+- [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION] + [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION] (master)
+
+## Project Structure
+
+```text
+backend/
+frontend/
+tests/
+```
+
+## Commands
+
+cd src; pytest; ruff check .
+
+## Code Style
+
+[e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]: Follow standard conventions
+
+## Recent Changes
+
+- master: Added [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION] + [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
+
+<!-- MANUAL ADDITIONS START -->
+<!-- MANUAL ADDITIONS END -->

+ 299 - 0
docs/superpowers/plans/2026-04-30-merchant-billing-mdid-filter.md

@@ -0,0 +1,299 @@
+# 商家账单日/周/月查询增加 mdId 过滤 实现计划
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** 为 `getzddaylist`、`getzdmeeklist`、`getzdmatlist` 三个接口增加可选的 `mdId` 门店过滤参数。
+
+**Architecture:** 在 Controller 层接收可选参数 `mdId`,传入 Mapper 层 SQL。利用 `#{mdId} IS NULL OR md_id = #{mdId}` 模式在 `@Select` 注解中实现动态过滤,无需改用 XML。同时更新对应的统计查询(`getdaysum`/`getmeeksum`/`getmatsum` 及 `getShDaysum`/`getShMeeksum`/`getshMonthsum`),保证列表和汇总数据一致。
+
+**Tech Stack:** Java, Spring Boot, MyBatis Plus, MySQL
+
+---
+
+## 涉及文件
+
+| 文件 | 操作 | 说明 |
+|------|------|------|
+| `ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java` | 修改 | 3 个接口方法增加 mdId 参数 |
+| `ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java` | 修改 | 6 个 `@Select` SQL 增加 mdId 条件 |
+
+---
+
+### Task 1: Mapper 层 — 修改日账单相关 SQL
+
+**Files:**
+- Modify: `ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java`
+
+- [ ] **Step 1: 修改 `getdaylist` 方法 — 增加 mdId 参数和 SQL 条件**
+
+将方法签名从:
+```java
+List<UserBilling> getdaylist(@Param("shid") Long shid, @Param("riqi") String riqi,@Param("page") Long page,@Param("size") Long size);
+```
+改为:
+```java
+List<UserBilling> getdaylist(@Param("shid") Long shid, @Param("riqi") String riqi, @Param("mdId") Long mdId, @Param("page") Long page, @Param("size") Long size);
+```
+
+SQL 从:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and date_format (cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s') ORDER BY id desc limit #{page},#{size}
+```
+改为:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and date_format (cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s') ORDER BY id desc limit #{page},#{size}
+```
+
+- [ ] **Step 2: 修改 `getdaysum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and date_format (cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s') and state=0
+```
+改为:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and date_format (cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s') and state=0
+```
+
+- [ ] **Step 3: 修改 `getShDaysum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `b.user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR b.md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and date_format (b.cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (b.cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s')
+```
+改为:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and (#{mdId} IS NULL OR b.md_id = #{mdId}) and date_format (b.cretim,'%Y-%m-%d %H:%i:%s') >= date_format (CONCAT(#{riqi}, ' 00:00:00'),'%Y-%m-%d %H:%i:%s') and date_format (b.cretim,'%Y-%m-%d %H:%i:%s') <= date_format (CONCAT(#{riqi}, ' 23:59:59'),'%Y-%m-%d %H:%i:%s')
+```
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java
+git commit -m "feat(billing): 日账单 mapper 增加 mdId 可选过滤"
+```
+
+---
+
+### Task 2: Mapper 层 — 修改周账单相关 SQL
+
+**Files:**
+- Modify: `ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java`
+
+- [ ] **Step 1: 修改 `getmeeklist` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and WEEK(cretim) = WEEK(#{riqi}) and  YEAR(cretim) = YEAR(#{riqi}) ORDER BY id desc limit #{page},#{size}
+```
+改为:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and WEEK(cretim) = WEEK(#{riqi}) and  YEAR(cretim) = YEAR(#{riqi}) ORDER BY id desc limit #{page},#{size}
+```
+
+- [ ] **Step 2: 修改 `getmeeksum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru ,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and  WEEK(cretim) = WEEK(#{riqi}) and  YEAR(cretim) = YEAR(#{riqi}) and state=0
+```
+改为:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru ,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and  WEEK(cretim) = WEEK(#{riqi}) and  YEAR(cretim) = YEAR(#{riqi}) and state=0
+```
+
+- [ ] **Step 3: 修改 `getShMeeksum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `b.user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR b.md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and  WEEK(b.cretim) = WEEK(#{riqi}) and  YEAR(b.cretim) = YEAR(#{riqi}) and b.state=0
+```
+改为:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and (#{mdId} IS NULL OR b.md_id = #{mdId}) and  WEEK(b.cretim) = WEEK(#{riqi}) and  YEAR(b.cretim) = YEAR(#{riqi}) and b.state=0
+```
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java
+git commit -m "feat(billing): 周账单 mapper 增加 mdId 可选过滤"
+```
+
+---
+
+### Task 3: Mapper 层 — 修改月账单相关 SQL
+
+**Files:**
+- Modify: `ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java`
+
+- [ ] **Step 1: 修改 `getmatlist` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and DATE_FORMAT(cretim, '%Y-%m') = #{riqi}  ORDER BY id desc limit #{page},#{size}
+```
+改为:
+```sql
+SELECT * FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and DATE_FORMAT(cretim, '%Y-%m') = #{riqi}  ORDER BY id desc limit #{page},#{size}
+```
+
+- [ ] **Step 2: 修改 `getmatsum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru ,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and DATE_FORMAT(cretim, '%Y-%m') = #{riqi} and state=0
+```
+改为:
+```sql
+SELECT IFNULL(COUNT(1),0) AS sul,IFNULL(SUM(amount),0) AS shouru ,IFNULL(SUM(divvy),0) AS commission,IFNULL(SUM(tax),0) AS tax,IFNULL(SUM(behalf_amount),0) AS behalfAmount FROM user_billing WHERE type=0 and user_id=#{shid} and (#{mdId} IS NULL OR md_id = #{mdId}) and DATE_FORMAT(cretim, '%Y-%m') = #{riqi} and state=0
+```
+
+- [ ] **Step 3: 修改 `getshMonthsum` 方法 — 增加 mdId 参数和 SQL 条件**
+
+方法签名增加 `@Param("mdId") Long mdId`,SQL 在 `b.user_id=#{shid}` 后增加 `and (#{mdId} IS NULL OR b.md_id = #{mdId})`。
+
+原 SQL:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and DATE_FORMAT(b.cretim, '%Y-%m') = #{riqi} and b.state=0
+```
+改为:
+```sql
+SELECT IFNULL(SUM(o.food_amount),0) AS foodAmount,IFNULL(SUM(o.md_discount_amount),0)+IFNULL(SUM(o.md_sales_reduction),0) as shYh  FROM user_billing b left join pos_order o on b.dd_id=o.dd_id WHERE b.type=0 and b.user_id=#{shid} and (#{mdId} IS NULL OR b.md_id = #{mdId}) and DATE_FORMAT(b.cretim, '%Y-%m') = #{riqi} and b.state=0
+```
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserBillingMapper.java
+git commit -m "feat(billing): 月账单 mapper 增加 mdId 可选过滤"
+```
+
+---
+
+### Task 4: Controller 层 — 三个接口方法增加 mdId 参数
+
+**Files:**
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java`
+
+- [ ] **Step 1: 修改 `getzddaylist` 方法**
+
+在方法签名中增加 `@RequestParam(required = false) Long mdId` 参数,并在调用 mapper 时传入 `mdId`。
+
+修改前:
+```java
+public AjaxResult getzddaylist(@RequestHeader String token,
+                               @RequestParam Long page,
+                               @RequestParam Long size,
+                               @RequestParam String riqi,
+                               @RequestParam(required = false) Boolean isCancel
+) {
+```
+修改后:
+```java
+public AjaxResult getzddaylist(@RequestHeader String token,
+                               @RequestParam Long page,
+                               @RequestParam Long size,
+                               @RequestParam String riqi,
+                               @RequestParam(required = false) Boolean isCancel,
+                               @RequestParam(required = false) Long mdId
+) {
+```
+
+调用 mapper 处,将 `null` 改为 `mdId`:
+
+```java
+// 原:List<UserBilling> list = userBillingMapper.getdaylist(id, riqi, (page - 1) * size, size);
+List<UserBilling> list = userBillingMapper.getdaylist(id, riqi, mdId, (page - 1) * size, size);
+// 原:BillDTO sum = userBillingMapper.getdaysum(id, riqi);
+BillDTO sum = userBillingMapper.getdaysum(id, riqi, mdId);
+```
+
+以及商户统计处:
+```java
+// 原:ShBillingDto shBillingDto = userBillingMapper.getShDaysum(id, riqi);
+ShBillingDto shBillingDto = userBillingMapper.getShDaysum(id, riqi, mdId);
+```
+
+- [ ] **Step 2: 修改 `getzdmeeklist` 方法**
+
+在方法签名中增加 `@RequestParam(required = false) Long mdId` 参数:
+
+```java
+public AjaxResult getzdmeeklist(@RequestHeader String token,
+                                @RequestParam Long page,
+                                @RequestParam Long size,
+                                @RequestParam String riqi,
+                                @RequestParam(required = false) Boolean isCancel,
+                                @RequestParam(required = false) Long mdId) {
+```
+
+调用 mapper 处传入 `mdId`:
+```java
+List<UserBilling> list = userBillingMapper.getmeeklist(id, riqi, mdId, (page - 1) * size, size);
+BillDTO sum = userBillingMapper.getmeeksum(id, riqi, mdId);
+```
+
+以及商户统计处:
+```java
+ShBillingDto shBillingDto = userBillingMapper.getShMeeksum(id, riqi, mdId);
+```
+
+- [ ] **Step 3: 修改 `getzdmatlist` 方法**
+
+在方法签名中增加 `@RequestParam(required = false) Long mdId` 参数:
+
+```java
+public AjaxResult getzdmatlist(@RequestHeader String token,
+                               @RequestParam Long page,
+                               @RequestParam Long size,
+                               @RequestParam String riqi,
+                               @RequestParam(required = false) Boolean isCancel,
+                               @RequestParam(required = false) Long mdId) {
+```
+
+调用 mapper 处传入 `mdId`:
+```java
+List<UserBilling> list = userBillingMapper.getmatlist(id, riqi, mdId, (page - 1) * size, size);
+BillDTO sum = userBillingMapper.getmatsum(id, riqi, mdId);
+```
+
+以及商户统计处:
+```java
+ShBillingDto shBillingDto = userBillingMapper.getshMonthsum(id, riqi, mdId);
+```
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java
+git commit -m "feat(billing): 日/周/月账单接口增加 mdId 可选过滤参数"
+```
+
+---
+
+## Self-Review
+
+**Spec coverage:**
+- spec 要求 `getdaylist`、`getmeeklist`、`getmatlist` 增加 mdId 过滤 -> Task 1/2/3 (mapper) + Task 4 (controller) 覆盖
+- mdId 为非必需参数 -> 所有 SQL 使用 `(#{mdId} IS NULL OR md_id = #{mdId})` 模式,mdId 为 null 时不影响原逻辑
+
+**Placeholder scan:** 无 TBD/TODO,所有 SQL 和代码均完整提供。
+
+**Type consistency:** 所有 mapper 方法 mdId 参数类型为 `Long`,与 controller `@RequestParam` 和 `UserBilling.mdId` 字段类型一致。
+
+**Note:** 取消订单列表(`getDayCancleOrderList`/`getWeekCancleOrderList`/`getMonthCancleOrderList`)查询的是 `pos_order` 表而非 `user_billing` 表,spec 未要求对其增加 mdId 过滤,因此不在本次范围内。

+ 170 - 0
docs/superpowers/specs/2026-04-28-multi-country-expansion-design.md

@@ -0,0 +1,170 @@
+# 外卖多国扩展需求设计文档
+
+## 项目概述
+
+将现有外卖系统扩展至泰国、菲律宾、马来西亚、印尼,不新建系统,在现有台湾外卖基础上开多语言版本,分区域点餐。台湾上架时同步开通这四个国家的下载。不同定位展示不同商家,数据不隔离。
+
+**目标国家:** 台湾(已有)、泰国(TH)、菲律宾(PH)、马来西亚(MY)、印尼(ID)
+
+---
+
+## 1. 待确认需求
+
+### 1.1 用户国家识别方式(待定)
+
+用户打开 App 后,系统如何确定他应该看到哪个国家的商家。以下四种方案待选定:
+
+#### 方案 A:GPS 定位自动判断
+
+根据用户当前 GPS 经纬度调用 Google Maps 反向地理编码,自动确定国家。
+
+| 优点 | 缺点 |
+|------|------|
+| 用户零操作,体验最顺滑 | GPS 权限被拒绝时无法工作 |
+| 最准确,不存在选错的问题 | 首次加载慢(要等定位 + API 返回) |
+| 适合外卖场景(本身就是本地服务) | 跨境用户(边境城市)可能误判 |
+| 不需要额外的 UI 入口 | 调 Google Maps API 有费用 |
+
+#### 方案 B:用户手动选择国家
+
+App 首页或设置页提供国家切换入口(类似 Shopee 顶部国家标签)。
+
+| 优点 | 缺点 |
+|------|------|
+| 实现最简单,不依赖 GPS 和外部 API | 用户可能选错国家,看到无关商家 |
+| 响应快,无等待 | 用户换国家时需要手动操作,容易忘 |
+| 完全可控 | 每个新用户都要多一步操作 |
+| 适合"浏览型"场景 | 和外卖"就近点餐"的逻辑矛盾 |
+
+#### 方案 C:GPS 自动 + 手动切换
+
+默认 GPS 自动判断国家,但在 App 顶部提供切换入口。
+
+| 优点 | 缺点 |
+|------|------|
+| 兼顾自动和灵活 | 实现复杂度最高 |
+| 覆盖 GPS 不可用的 fallback | 需要额外设计国家切换 UI |
+| 支持帮异地朋友点餐等场景 | 切换后商家列表要全部刷新 |
+| 用户体验最优 | 两个逻辑路径都要测试和维护 |
+
+#### 方案 D:注册时绑定国家
+
+用户注册时选择所在国家,之后固定展示该国商家。
+
+| 优点 | 缺点 |
+|------|------|
+| 实现简单,一次选择终身生效 | 用户搬家/换国家后很不方便 |
+| 不依赖 GPS | 出差/旅游时无法使用当地外卖 |
+| 数据归属清晰 | 不适合东南亚人群流动频繁的场景 |
+| 注册信息即国家信息 | 修改国家可能涉及钱包余额等复杂问题 |
+
+**初步建议:方案 C**,可分阶段实施(先 GPS 自动,后加手动切换)。
+
+---
+
+## 2. 已确认需求
+
+### 2.1 核心原则
+
+- **不新建系统** — 复用现有台湾外卖代码,多语言 + 分区域
+- **数据不隔离** — 所有国家共享同一数据库
+- **定位驱动商家列表** — 不同位置搜索到的商家不同
+- **同步上架** — 台湾上架时同步开通 TH/PH/MY/ID 的 App 下载
+
+### 2.2 当前系统现状(已确认可行)
+
+| 能力 | 状态 | 说明 |
+|------|------|------|
+| 定位搜商家 | 已支持 | `ST_DISTANCE()` 按经纬度排序,`area` 字段过滤 |
+| 数据不隔离 | 已支持 | 单库架构,无需改动 |
+| 多语言框架 | 已支持 | 已有 zh_CN/zh_TW/en/vi 四种语言的 i18n |
+| 区域点餐 | 已支持 | 商家按 area + 经纬度距离过滤 |
+
+### 2.3 必须改造的模块(已确认)
+
+| 问题 | 严重程度 | 说明 |
+|------|----------|------|
+| 无国家/地区字段 | 高 | `pos_store` 需加 `country` 字段,商家查询加国家过滤 |
+| 货币固定 VND | 高 | 需按国家配置货币(THB/PHP/MYR/IDR/TWD) |
+| 支付只有 ZaloPay | 高 | 各国需对接本地主流支付方式 |
+| 商家注册无国家信息 | 中 | 入驻流程需加国家选择 |
+| Google Maps Key 管理 | 低 | 各国共用 Google Maps,注意 API 配额 |
+
+---
+
+## 3. 待讨论需求
+
+以下问题尚未讨论,后续逐一确认:
+
+### 3.1 货币与定价(已确认)
+- **各国独立定价** — 同一品牌在各国使用不同商家号管理,各自独立维护菜品和价格,不存在跨国同商品定价问题
+- 各商家号绑定所在国家,使用当地货币定价(TH/THB, PH/PHP, MY/MYR, ID/IDR, TW/TWD)
+- 平台佣金比例是否各国不同?待确认
+
+### 3.2 支付方式(待调研)
+- 每个国家需要接入哪些本地支付?**待调研后确定**
+  - 泰国候选:PromptPay, TrueMoney
+  - 菲律宾候选:GCash, Maya
+  - 马来候选:Touch'n Go, FPX
+  - 印尼候选:GoPay, OVO
+  - 台湾:待确认
+- 接入策略待定:每国一种 / 每国 2-3 种 / 聚合支付平台
+- 钱包余额是否按国家隔离?待确认
+- 跨国充值/提现如何处理?待确认
+
+### 3.3 多语言(待定)
+- 每个国家需要支持哪些语言?待定
+  - 候选方案 A:当地语言 + 英语
+  - 候选方案 B:中文 + 英语 + 当地语言
+  - 候选方案 C:各国不同,逐个确认
+- 商家端的语言支持范围?待定
+- 菜品名称是否需要商家自己填多语言版本?待定
+
+### 3.4 商家管理(待定)
+- 商家入驻审核是各国独立还是统一管理?待定
+  - 候选方案 A:统一后台,通过国家字段筛选区分
+  - 候选方案 B:各国独立管理后台
+- 商家可以同时在多国营业吗?待定(已确认同一品牌用不同商家号管理)
+- 各国的商家分类/标签是否统一?待定
+
+### 3.5 配送与骑手(待定)
+- 配送费计算规则各国是否不同?待定
+  - 候选方案 A:统一算法 + 各国参数配置
+  - 候选方案 B:各国独立规则
+- 骑手是按国家分开管理还是统一?待定
+- 配送范围(公里数)各国是否不同?待定
+
+### 3.6 法律与合规(待定)
+- 各国的税务处理(增值税/消费税)?待定
+- 食品安全认证要求是否不同?待定
+- 隐私政策和用户协议是否需要各国版本?待定
+
+### 3.7 运营与后台(待定)
+- 后台管理是否需要按国家区分权限?待定
+- 各国的促销/优惠券活动是否独立?待定
+- 客服系统是否按国家分开?待定
+
+---
+
+## 4. 技术架构
+
+### 4.1 当前技术栈
+
+- Spring Boot 3.3.5 + Java 21
+- MyBatis-Plus 3.0.3 + MySQL 8.2.0
+- Redis 缓存
+- Google Maps API(地理编码、路线)
+- ZaloPay(越南支付)
+- JWT 认证
+
+### 4.2 核心改造点(概要,详细方案待确认后补充)
+
+1. **商家查询** — `PosStoreMapper` 加 `country` 过滤
+2. **货币系统** — 按国家配置货币单位
+3. **支付网关** — 按国家路由到不同支付渠道
+4. **商家入驻** — 注册时绑定国家
+5. **App 配置** — 按国家加载语言、货币、支付方式
+
+---
+
+*文档状态:需求收集中,待逐项确认后完善*

+ 121 - 0
docs/superpowers/specs/2026-04-30-qr-table-ordering-design.md

@@ -0,0 +1,121 @@
+# 扫码桌号点餐设计
+
+日期: 2026-04-30
+
+## 背景
+
+用户在 APP 中扫描餐桌二维码进入菜单点餐,订单需要关联到具体的餐桌码,商家根据订单上的桌号送餐。
+
+## 现有基础
+
+- `TableQrcode` 实体和完整 CRUD API 已实现(创建、列表、扫码入口等)
+- `PosOrder` 已有 `tableNum` 字段和 `type=2`(堂食)订单类型
+- `OrderCreateInput` 已接收 `tableNum`
+- `UserOrderController` 已将 `tableNum` 写入父订单和子订单
+- 扫码入口 `/table-qrcode/scan` 已根据码类型跳转,URL 携带 `tableId`
+
+两种餐桌码:
+- **档口码**(type=0):直接进入该档口菜单
+- **通用码**(type=1):进入夜市所有档口选择页
+
+## 方案
+
+前端全程携带 tableId/tableNum,下单时作为可选参数传入。不做后端会话绑定,不做 Redis 存储。
+
+## 数据流
+
+```
+用户扫桌码
+  → app 调用 /table-qrcode/scan?tableId=xxx(已有)
+  → app 从 URL 获取 tableId
+  → 用户浏览菜单、选商品
+  → 提交订单时传入 tableId(可选)+ tableNum(可选)
+  → 后端校验 tableId 有效性,以码记录中的 tableNo 为桌号权威来源
+  → 写入 PosOrder.tableId + PosOrder.tableNum
+  → 商家端订单详情展示桌号
+```
+
+## 后端改动
+
+### 1. 数据库
+
+```sql
+ALTER TABLE pos_order ADD COLUMN table_id BIGINT DEFAULT NULL COMMENT '餐桌码ID';
+```
+
+如果 `order_parent` 表也需要记录 tableId,同理加字段。
+
+### 2. PosOrder 实体
+
+新增字段:
+
+```java
+/** 餐桌码ID(关联 table_qrcode 表) */
+private Long tableId;
+```
+
+`tableNum` 已存在,保持不变。
+
+### 3. OrderCreateInput DTO
+
+新增字段:
+
+```java
+/** 餐桌码ID(可选,扫码点餐时传入) */
+private Long tableId;
+```
+
+### 4. OrderParent(如需要)
+
+同样新增 `tableId` 字段,与 `tableNum` 对应。
+
+### 5. UserOrderController
+
+在 `createOrderChild` 方法中,`posOrder.setTableNum(input.getTableNum())` 旁新增:
+
+```java
+posOrder.setTableId(input.getTableId());
+```
+
+`createOrderParent` 同理。
+
+### 6. 校验逻辑
+
+如果 `tableId != null`:
+1. 查询 `table_qrcode` 表,确认码存在且未停用(status != 1)
+2. 从码记录中取出 `tableNo`,覆盖前端传入的 `tableNum`(以数据库为准)
+3. 码不存在或已停用则报错
+
+```java
+if (input.getTableId() != null) {
+    TableQrcode qrcode = tableQrcodeService.selectTableQrcodeById(input.getTableId());
+    if (qrcode == null) {
+        throw new ServiceException("餐桌码不存在");
+    }
+    if (qrcode.getStatus() != null && qrcode.getStatus() == 1) {
+        throw new ServiceException("该餐桌码已停用");
+    }
+    input.setTableNum(qrcode.getTableNo());
+}
+```
+
+### 7. 商家端展示
+
+无需新页面。`PosOrder` 返回时自动包含 `tableId` 和 `tableNum`,商家端前端在订单详情中展示桌号即可。
+
+## 不涉及的范围
+
+- 餐桌状态管理(占用/释放)
+- 多次加餐/拼单
+- 按桌号分组查询
+- 扫码频率限制
+
+## 影响文件清单
+
+| 文件 | 改动 |
+|------|------|
+| `PosOrder.java` | 新增 `tableId` 字段 |
+| `OrderCreateInput.java` | 新增 `tableId` 字段 |
+| `OrderParent.java` | 新增 `tableId` 字段(如需要) |
+| `UserOrderController.java` | 设置 `tableId`,新增校验逻辑 |
+| SQL 迁移 | `pos_order` 加 `table_id` 列 |

+ 0 - 3
foodie_sj_vue/.browserslistrc

@@ -1,3 +0,0 @@
-> 1%
-last 2 versions
-not dead

+ 0 - 4
foodie_sj_vue/.env.development

@@ -1,4 +0,0 @@
-NODE_ENV  = 'development'
-VUE_APP_BASE_URL='http://localhost:8080'
-VUE_APP_BACKEND_URL='https://backend.awayqtw.com/prod-api/'
-

+ 0 - 3
foodie_sj_vue/.env.production

@@ -1,3 +0,0 @@
-ENV  = 'production'
-VUE_APP_BASE_URL='https://api.awayqtw.com'
-VUE_APP_BACKEND_URL='https://backend.awayqtw.com/prod-api/'

+ 0 - 3
foodie_sj_vue/.env.test

@@ -1,3 +0,0 @@
-ENV  = 'test'
-VUE_APP_BASE_URL='https://api.awayqtw.com'
-VUE_APP_BACKEND_URL='https://backend.awayqtw.com/prod-api/'

+ 0 - 23
foodie_sj_vue/.gitignore

@@ -1,23 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?

+ 0 - 19
foodie_sj_vue/README.md

@@ -1,19 +0,0 @@
-# eleliugang
-
-## Project setup
-```
-yarn install
-```
-
-### Compiles and hot-reloads for development
-```
-yarn serve
-```
-
-### Compiles and minifies for production
-```
-yarn build
-```
-
-### Customize configuration
-See [Configuration Reference](https://cli.vuejs.org/config/).

+ 0 - 5
foodie_sj_vue/babel.config.js

@@ -1,5 +0,0 @@
-module.exports = {
-  presets: [
-    '@vue/cli-plugin-babel/preset'
-  ]
-}

+ 0 - 19
foodie_sj_vue/jsconfig.json

@@ -1,19 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "es5",
-    "module": "esnext",
-    "baseUrl": "./",
-    "moduleResolution": "node",
-    "paths": {
-      "@/*": [
-        "src/*"
-      ]
-    },
-    "lib": [
-      "esnext",
-      "dom",
-      "dom.iterable",
-      "scripthost"
-    ]
-  }
-}

+ 0 - 10568
foodie_sj_vue/package-lock.json

@@ -1,10568 +0,0 @@
-{
-  "name": "eleliugang",
-  "version": "0.1.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "eleliugang",
-      "version": "0.1.0",
-      "dependencies": {
-        "@googlemaps/js-api-loader": "^1.16.2",
-        "axios": "^1.3.6",
-        "core-js": "^3.8.3",
-        "echarts": "^4.9.0",
-        "element-ui": "^2.15.13",
-        "file-saver": "2.0.5",
-        "js-cookie": "^3.0.5",
-        "jsencrypt": "^3.3.2",
-        "v-charts": "^1.19.0",
-        "vue": "^2.6.14",
-        "vue-i18n": "^7.3.2",
-        "vue-json-excel": "^0.3.0",
-        "vue-router": "^3.5.1"
-      },
-      "devDependencies": {
-        "@vue/cli-plugin-babel": "~5.0.0",
-        "@vue/cli-plugin-router": "~5.0.0",
-        "@vue/cli-service": "~5.0.0",
-        "vue-template-compiler": "^2.6.14"
-      }
-    },
-    "node_modules/@achrinza/node-ipc": {
-      "version": "9.2.8",
-      "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.8.tgz",
-      "integrity": "sha512-DSzEEkbMYbAUVlhy7fg+BzccoRuSQzqHbIPGxGv19OJ2WKwS3/9ChAnQcII4g+GujcHhyJ8BUuOVAx/S5uAfQg==",
-      "dev": true,
-      "dependencies": {
-        "@node-ipc/js-queue": "2.0.3",
-        "event-pubsub": "4.3.0",
-        "js-message": "1.0.7"
-      },
-      "engines": {
-        "node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21"
-      }
-    },
-    "node_modules/@ampproject/remapping": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
-      "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.0",
-        "@jridgewell/trace-mapping": "^0.3.9"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@babel/code-frame": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
-      "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/highlight": "^7.23.4",
-        "chalk": "^2.4.2"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/compat-data": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
-      "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/core": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz",
-      "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==",
-      "dev": true,
-      "dependencies": {
-        "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.23.5",
-        "@babel/generator": "^7.23.5",
-        "@babel/helper-compilation-targets": "^7.22.15",
-        "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helpers": "^7.23.5",
-        "@babel/parser": "^7.23.5",
-        "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.5",
-        "@babel/types": "^7.23.5",
-        "convert-source-map": "^2.0.0",
-        "debug": "^4.1.0",
-        "gensync": "^1.0.0-beta.2",
-        "json5": "^2.2.3",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/babel"
-      }
-    },
-    "node_modules/@babel/generator": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz",
-      "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.23.5",
-        "@jridgewell/gen-mapping": "^0.3.2",
-        "@jridgewell/trace-mapping": "^0.3.17",
-        "jsesc": "^2.5.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-annotate-as-pure": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
-      "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
-      "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.15"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-compilation-targets": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
-      "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/compat-data": "^7.22.9",
-        "@babel/helper-validator-option": "^7.22.15",
-        "browserslist": "^4.21.9",
-        "lru-cache": "^5.1.1",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-create-class-features-plugin": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.5.tgz",
-      "integrity": "sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.22.5",
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-function-name": "^7.23.0",
-        "@babel/helper-member-expression-to-functions": "^7.23.0",
-        "@babel/helper-optimise-call-expression": "^7.22.5",
-        "@babel/helper-replace-supers": "^7.22.20",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-create-regexp-features-plugin": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz",
-      "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.22.5",
-        "regexpu-core": "^5.3.1",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-define-polyfill-provider": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz",
-      "integrity": "sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.22.6",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "debug": "^4.1.1",
-        "lodash.debounce": "^4.0.8",
-        "resolve": "^1.14.2"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/@babel/helper-environment-visitor": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
-      "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-function-name": {
-      "version": "7.23.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
-      "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/template": "^7.22.15",
-        "@babel/types": "^7.23.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-hoist-variables": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
-      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-member-expression-to-functions": {
-      "version": "7.23.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
-      "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.23.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-module-imports": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
-      "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.15"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-module-transforms": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
-      "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-module-imports": "^7.22.15",
-        "@babel/helper-simple-access": "^7.22.5",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/helper-validator-identifier": "^7.22.20"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-optimise-call-expression": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
-      "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-plugin-utils": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
-      "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-remap-async-to-generator": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz",
-      "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.22.5",
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-wrap-function": "^7.22.20"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-replace-supers": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz",
-      "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-member-expression-to-functions": "^7.22.15",
-        "@babel/helper-optimise-call-expression": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-simple-access": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
-      "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
-      "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-split-export-declaration": {
-      "version": "7.22.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
-      "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/types": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-string-parser": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
-      "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
-      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-validator-option": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
-      "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-wrap-function": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz",
-      "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-function-name": "^7.22.5",
-        "@babel/template": "^7.22.15",
-        "@babel/types": "^7.22.19"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helpers": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz",
-      "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.5",
-        "@babel/types": "^7.23.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/highlight": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
-      "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.22.20",
-        "chalk": "^2.4.2",
-        "js-tokens": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/parser": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz",
-      "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==",
-      "bin": {
-        "parser": "bin/babel-parser.js"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz",
-      "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz",
-      "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
-        "@babel/plugin-transform-optional-chaining": "^7.23.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.13.0"
-      }
-    },
-    "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.3.tgz",
-      "integrity": "sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-proposal-class-properties": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
-      "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
-      "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.18.6",
-        "@babel/helper-plugin-utils": "^7.18.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-proposal-decorators": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.5.tgz",
-      "integrity": "sha512-6IsY8jOeWibsengGlWIezp7cuZEFzNlAghFpzh9wiZwhQ42/hRcPnY/QV9HJoKTlujupinSlnQPiEy/u2C1ZfQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.23.5",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-replace-supers": "^7.22.20",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/plugin-syntax-decorators": "^7.23.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-proposal-private-property-in-object": {
-      "version": "7.21.0-placeholder-for-preset-env.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
-      "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-async-generators": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
-      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-class-properties": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
-      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.12.13"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-class-static-block": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
-      "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-decorators": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.23.3.tgz",
-      "integrity": "sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-dynamic-import": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
-      "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-export-namespace-from": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
-      "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.3"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-import-assertions": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz",
-      "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-import-attributes": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz",
-      "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-import-meta": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
-      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-json-strings": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
-      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-jsx": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz",
-      "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
-      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
-      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-numeric-separator": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
-      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-object-rest-spread": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
-      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
-      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-optional-chaining": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
-      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-private-property-in-object": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
-      "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-top-level-await": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
-      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
-      "version": "7.18.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
-      "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.18.6",
-        "@babel/helper-plugin-utils": "^7.18.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-arrow-functions": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz",
-      "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-async-generator-functions": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.4.tgz",
-      "integrity": "sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-remap-async-to-generator": "^7.22.20",
-        "@babel/plugin-syntax-async-generators": "^7.8.4"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-async-to-generator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz",
-      "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-remap-async-to-generator": "^7.22.20"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-block-scoped-functions": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz",
-      "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-block-scoping": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz",
-      "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-class-properties": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz",
-      "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-class-static-block": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz",
-      "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-class-static-block": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.12.0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-classes": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz",
-      "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.22.5",
-        "@babel/helper-compilation-targets": "^7.22.15",
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-function-name": "^7.23.0",
-        "@babel/helper-optimise-call-expression": "^7.22.5",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-replace-supers": "^7.22.20",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "globals": "^11.1.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-computed-properties": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz",
-      "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/template": "^7.22.15"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-destructuring": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz",
-      "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-dotall-regex": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz",
-      "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-duplicate-keys": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz",
-      "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-dynamic-import": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz",
-      "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-dynamic-import": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-exponentiation-operator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz",
-      "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-export-namespace-from": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz",
-      "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-for-of": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz",
-      "integrity": "sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-function-name": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz",
-      "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.22.15",
-        "@babel/helper-function-name": "^7.23.0",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-json-strings": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz",
-      "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-json-strings": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-literals": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz",
-      "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-logical-assignment-operators": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz",
-      "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-member-expression-literals": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz",
-      "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-modules-amd": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz",
-      "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-modules-commonjs": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz",
-      "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-simple-access": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-modules-systemjs": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz",
-      "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-hoist-variables": "^7.22.5",
-        "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-validator-identifier": "^7.22.20"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-modules-umd": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz",
-      "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz",
-      "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.22.5",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-new-target": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz",
-      "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz",
-      "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-numeric-separator": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz",
-      "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-numeric-separator": "^7.10.4"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-object-rest-spread": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz",
-      "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/compat-data": "^7.23.3",
-        "@babel/helper-compilation-targets": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-        "@babel/plugin-transform-parameters": "^7.23.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-object-super": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz",
-      "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-replace-supers": "^7.22.20"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-optional-catch-binding": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz",
-      "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-optional-chaining": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz",
-      "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
-        "@babel/plugin-syntax-optional-chaining": "^7.8.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-parameters": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz",
-      "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-private-methods": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz",
-      "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-private-property-in-object": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz",
-      "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.22.5",
-        "@babel/helper-create-class-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-property-literals": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz",
-      "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-regenerator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz",
-      "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "regenerator-transform": "^0.15.2"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-reserved-words": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz",
-      "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-runtime": {
-      "version": "7.23.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.4.tgz",
-      "integrity": "sha512-ITwqpb6V4btwUG0YJR82o2QvmWrLgDnx/p2A3CTPYGaRgULkDiC0DRA2C4jlRB9uXGUEfaSS/IGHfVW+ohzYDw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "babel-plugin-polyfill-corejs2": "^0.4.6",
-        "babel-plugin-polyfill-corejs3": "^0.8.5",
-        "babel-plugin-polyfill-regenerator": "^0.5.3",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-shorthand-properties": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz",
-      "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-spread": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz",
-      "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-sticky-regex": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz",
-      "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-template-literals": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz",
-      "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-typeof-symbol": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz",
-      "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-unicode-escapes": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz",
-      "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-unicode-property-regex": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz",
-      "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-unicode-regex": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz",
-      "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-unicode-sets-regex": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz",
-      "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/preset-env": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.5.tgz",
-      "integrity": "sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==",
-      "dev": true,
-      "dependencies": {
-        "@babel/compat-data": "^7.23.5",
-        "@babel/helper-compilation-targets": "^7.22.15",
-        "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-validator-option": "^7.23.5",
-        "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3",
-        "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3",
-        "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.3",
-        "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
-        "@babel/plugin-syntax-async-generators": "^7.8.4",
-        "@babel/plugin-syntax-class-properties": "^7.12.13",
-        "@babel/plugin-syntax-class-static-block": "^7.14.5",
-        "@babel/plugin-syntax-dynamic-import": "^7.8.3",
-        "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
-        "@babel/plugin-syntax-import-assertions": "^7.23.3",
-        "@babel/plugin-syntax-import-attributes": "^7.23.3",
-        "@babel/plugin-syntax-import-meta": "^7.10.4",
-        "@babel/plugin-syntax-json-strings": "^7.8.3",
-        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
-        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
-        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
-        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
-        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
-        "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
-        "@babel/plugin-syntax-top-level-await": "^7.14.5",
-        "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
-        "@babel/plugin-transform-arrow-functions": "^7.23.3",
-        "@babel/plugin-transform-async-generator-functions": "^7.23.4",
-        "@babel/plugin-transform-async-to-generator": "^7.23.3",
-        "@babel/plugin-transform-block-scoped-functions": "^7.23.3",
-        "@babel/plugin-transform-block-scoping": "^7.23.4",
-        "@babel/plugin-transform-class-properties": "^7.23.3",
-        "@babel/plugin-transform-class-static-block": "^7.23.4",
-        "@babel/plugin-transform-classes": "^7.23.5",
-        "@babel/plugin-transform-computed-properties": "^7.23.3",
-        "@babel/plugin-transform-destructuring": "^7.23.3",
-        "@babel/plugin-transform-dotall-regex": "^7.23.3",
-        "@babel/plugin-transform-duplicate-keys": "^7.23.3",
-        "@babel/plugin-transform-dynamic-import": "^7.23.4",
-        "@babel/plugin-transform-exponentiation-operator": "^7.23.3",
-        "@babel/plugin-transform-export-namespace-from": "^7.23.4",
-        "@babel/plugin-transform-for-of": "^7.23.3",
-        "@babel/plugin-transform-function-name": "^7.23.3",
-        "@babel/plugin-transform-json-strings": "^7.23.4",
-        "@babel/plugin-transform-literals": "^7.23.3",
-        "@babel/plugin-transform-logical-assignment-operators": "^7.23.4",
-        "@babel/plugin-transform-member-expression-literals": "^7.23.3",
-        "@babel/plugin-transform-modules-amd": "^7.23.3",
-        "@babel/plugin-transform-modules-commonjs": "^7.23.3",
-        "@babel/plugin-transform-modules-systemjs": "^7.23.3",
-        "@babel/plugin-transform-modules-umd": "^7.23.3",
-        "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
-        "@babel/plugin-transform-new-target": "^7.23.3",
-        "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
-        "@babel/plugin-transform-numeric-separator": "^7.23.4",
-        "@babel/plugin-transform-object-rest-spread": "^7.23.4",
-        "@babel/plugin-transform-object-super": "^7.23.3",
-        "@babel/plugin-transform-optional-catch-binding": "^7.23.4",
-        "@babel/plugin-transform-optional-chaining": "^7.23.4",
-        "@babel/plugin-transform-parameters": "^7.23.3",
-        "@babel/plugin-transform-private-methods": "^7.23.3",
-        "@babel/plugin-transform-private-property-in-object": "^7.23.4",
-        "@babel/plugin-transform-property-literals": "^7.23.3",
-        "@babel/plugin-transform-regenerator": "^7.23.3",
-        "@babel/plugin-transform-reserved-words": "^7.23.3",
-        "@babel/plugin-transform-shorthand-properties": "^7.23.3",
-        "@babel/plugin-transform-spread": "^7.23.3",
-        "@babel/plugin-transform-sticky-regex": "^7.23.3",
-        "@babel/plugin-transform-template-literals": "^7.23.3",
-        "@babel/plugin-transform-typeof-symbol": "^7.23.3",
-        "@babel/plugin-transform-unicode-escapes": "^7.23.3",
-        "@babel/plugin-transform-unicode-property-regex": "^7.23.3",
-        "@babel/plugin-transform-unicode-regex": "^7.23.3",
-        "@babel/plugin-transform-unicode-sets-regex": "^7.23.3",
-        "@babel/preset-modules": "0.1.6-no-external-plugins",
-        "babel-plugin-polyfill-corejs2": "^0.4.6",
-        "babel-plugin-polyfill-corejs3": "^0.8.5",
-        "babel-plugin-polyfill-regenerator": "^0.5.3",
-        "core-js-compat": "^3.31.0",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/preset-modules": {
-      "version": "0.1.6-no-external-plugins",
-      "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
-      "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.0.0",
-        "@babel/types": "^7.4.4",
-        "esutils": "^2.0.2"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/@babel/regjsgen": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
-      "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
-      "dev": true
-    },
-    "node_modules/@babel/runtime": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz",
-      "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==",
-      "dev": true,
-      "dependencies": {
-        "regenerator-runtime": "^0.14.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/template": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
-      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.22.13",
-        "@babel/parser": "^7.22.15",
-        "@babel/types": "^7.22.15"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/traverse": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz",
-      "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.23.5",
-        "@babel/generator": "^7.23.5",
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-function-name": "^7.23.0",
-        "@babel/helper-hoist-variables": "^7.22.5",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/parser": "^7.23.5",
-        "@babel/types": "^7.23.5",
-        "debug": "^4.1.0",
-        "globals": "^11.1.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/types": {
-      "version": "7.23.5",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz",
-      "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-string-parser": "^7.23.4",
-        "@babel/helper-validator-identifier": "^7.22.20",
-        "to-fast-properties": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@discoveryjs/json-ext": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
-      "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/@googlemaps/js-api-loader": {
-      "version": "1.16.2",
-      "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.2.tgz",
-      "integrity": "sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA==",
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3"
-      }
-    },
-    "node_modules/@hapi/hoek": {
-      "version": "9.3.0",
-      "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
-      "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
-      "dev": true
-    },
-    "node_modules/@hapi/topo": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
-      "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
-      "dev": true,
-      "dependencies": {
-        "@hapi/hoek": "^9.0.0"
-      }
-    },
-    "node_modules/@jridgewell/gen-mapping": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
-      "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/set-array": "^1.0.1",
-        "@jridgewell/sourcemap-codec": "^1.4.10",
-        "@jridgewell/trace-mapping": "^0.3.9"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
-      "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/set-array": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
-      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/source-map": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
-      "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.0",
-        "@jridgewell/trace-mapping": "^0.3.9"
-      }
-    },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.4.15",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
-      "dev": true
-    },
-    "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.20",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
-      "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/resolve-uri": "^3.1.0",
-        "@jridgewell/sourcemap-codec": "^1.4.14"
-      }
-    },
-    "node_modules/@leichtgewicht/ip-codec": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
-      "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
-      "dev": true
-    },
-    "node_modules/@node-ipc/js-queue": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz",
-      "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==",
-      "dev": true,
-      "dependencies": {
-        "easy-stack": "1.0.1"
-      },
-      "engines": {
-        "node": ">=1.0.0"
-      }
-    },
-    "node_modules/@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@polka/url": {
-      "version": "1.0.0-next.24",
-      "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.24.tgz",
-      "integrity": "sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==",
-      "dev": true
-    },
-    "node_modules/@sideway/address": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
-      "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
-      "dev": true,
-      "dependencies": {
-        "@hapi/hoek": "^9.0.0"
-      }
-    },
-    "node_modules/@sideway/formula": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
-      "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
-      "dev": true
-    },
-    "node_modules/@sideway/pinpoint": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
-      "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
-      "dev": true
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz",
-      "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^3.0.0",
-        "error-stack-parser": "^2.0.6",
-        "string-width": "^4.2.3",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      },
-      "peerDependencies": {
-        "webpack": "^4.0.0 || ^5.0.0"
-      }
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@soda/get-current-script": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz",
-      "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
-      "dev": true
-    },
-    "node_modules/@trysound/sax": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
-      "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/@types/body-parser": {
-      "version": "1.19.5",
-      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
-      "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
-      "dev": true,
-      "dependencies": {
-        "@types/connect": "*",
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/bonjour": {
-      "version": "3.5.13",
-      "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz",
-      "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/connect": {
-      "version": "3.4.38",
-      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
-      "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/connect-history-api-fallback": {
-      "version": "1.5.4",
-      "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz",
-      "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==",
-      "dev": true,
-      "dependencies": {
-        "@types/express-serve-static-core": "*",
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/eslint": {
-      "version": "8.44.8",
-      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz",
-      "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==",
-      "dev": true,
-      "dependencies": {
-        "@types/estree": "*",
-        "@types/json-schema": "*"
-      }
-    },
-    "node_modules/@types/eslint-scope": {
-      "version": "3.7.7",
-      "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
-      "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
-      "dev": true,
-      "dependencies": {
-        "@types/eslint": "*",
-        "@types/estree": "*"
-      }
-    },
-    "node_modules/@types/estree": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
-      "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
-      "dev": true
-    },
-    "node_modules/@types/express": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
-      "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/body-parser": "*",
-        "@types/express-serve-static-core": "^4.17.33",
-        "@types/qs": "*",
-        "@types/serve-static": "*"
-      }
-    },
-    "node_modules/@types/express-serve-static-core": {
-      "version": "4.17.41",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz",
-      "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*",
-        "@types/qs": "*",
-        "@types/range-parser": "*",
-        "@types/send": "*"
-      }
-    },
-    "node_modules/@types/html-minifier-terser": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
-      "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==",
-      "dev": true
-    },
-    "node_modules/@types/http-errors": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
-      "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
-      "dev": true
-    },
-    "node_modules/@types/http-proxy": {
-      "version": "1.17.14",
-      "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz",
-      "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/json-schema": {
-      "version": "7.0.15",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
-      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
-      "dev": true
-    },
-    "node_modules/@types/mime": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
-      "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
-      "dev": true
-    },
-    "node_modules/@types/minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
-      "dev": true
-    },
-    "node_modules/@types/node": {
-      "version": "20.10.4",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
-      "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
-      "dev": true,
-      "dependencies": {
-        "undici-types": "~5.26.4"
-      }
-    },
-    "node_modules/@types/node-forge": {
-      "version": "1.3.10",
-      "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz",
-      "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/normalize-package-data": {
-      "version": "2.4.4",
-      "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
-      "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
-      "dev": true
-    },
-    "node_modules/@types/parse-json": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
-      "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
-      "dev": true
-    },
-    "node_modules/@types/qs": {
-      "version": "6.9.10",
-      "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz",
-      "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==",
-      "dev": true
-    },
-    "node_modules/@types/range-parser": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
-      "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
-      "dev": true
-    },
-    "node_modules/@types/retry": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
-      "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
-      "dev": true
-    },
-    "node_modules/@types/send": {
-      "version": "0.17.4",
-      "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
-      "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
-      "dev": true,
-      "dependencies": {
-        "@types/mime": "^1",
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/serve-index": {
-      "version": "1.9.4",
-      "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz",
-      "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==",
-      "dev": true,
-      "dependencies": {
-        "@types/express": "*"
-      }
-    },
-    "node_modules/@types/serve-static": {
-      "version": "1.15.5",
-      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
-      "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/http-errors": "*",
-        "@types/mime": "*",
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/sockjs": {
-      "version": "0.3.36",
-      "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz",
-      "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/ws": {
-      "version": "8.5.10",
-      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
-      "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@vue/babel-helper-vue-jsx-merge-props": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
-      "integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==",
-      "dev": true
-    },
-    "node_modules/@vue/babel-helper-vue-transform-on": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.1.5.tgz",
-      "integrity": "sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==",
-      "dev": true
-    },
-    "node_modules/@vue/babel-plugin-jsx": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.5.tgz",
-      "integrity": "sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.22.5",
-        "@babel/plugin-syntax-jsx": "^7.22.5",
-        "@babel/template": "^7.22.5",
-        "@babel/traverse": "^7.22.5",
-        "@babel/types": "^7.22.5",
-        "@vue/babel-helper-vue-transform-on": "^1.1.5",
-        "camelcase": "^6.3.0",
-        "html-tags": "^3.3.1",
-        "svg-tags": "^1.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-plugin-transform-vue-jsx": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz",
-      "integrity": "sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.0.0",
-        "@babel/plugin-syntax-jsx": "^7.2.0",
-        "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
-        "html-tags": "^2.0.0",
-        "lodash.kebabcase": "^4.1.1",
-        "svg-tags": "^1.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
-      "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@vue/babel-preset-app": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.8.tgz",
-      "integrity": "sha512-yl+5qhpjd8e1G4cMXfORkkBlvtPCIgmRf3IYCWYDKIQ7m+PPa5iTm4feiNmCMD6yGqQWMhhK/7M3oWGL9boKwg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/core": "^7.12.16",
-        "@babel/helper-compilation-targets": "^7.12.16",
-        "@babel/helper-module-imports": "^7.12.13",
-        "@babel/plugin-proposal-class-properties": "^7.12.13",
-        "@babel/plugin-proposal-decorators": "^7.12.13",
-        "@babel/plugin-syntax-dynamic-import": "^7.8.3",
-        "@babel/plugin-syntax-jsx": "^7.12.13",
-        "@babel/plugin-transform-runtime": "^7.12.15",
-        "@babel/preset-env": "^7.12.16",
-        "@babel/runtime": "^7.12.13",
-        "@vue/babel-plugin-jsx": "^1.0.3",
-        "@vue/babel-preset-jsx": "^1.1.2",
-        "babel-plugin-dynamic-import-node": "^2.3.3",
-        "core-js": "^3.8.3",
-        "core-js-compat": "^3.8.3",
-        "semver": "^7.3.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "*",
-        "core-js": "^3",
-        "vue": "^2 || ^3.2.13"
-      },
-      "peerDependenciesMeta": {
-        "core-js": {
-          "optional": true
-        },
-        "vue": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/babel-preset-app/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/@vue/babel-preset-app/node_modules/semver": {
-      "version": "7.5.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/@vue/babel-preset-app/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/@vue/babel-preset-jsx": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.4.0.tgz",
-      "integrity": "sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==",
-      "dev": true,
-      "dependencies": {
-        "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
-        "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
-        "@vue/babel-sugar-composition-api-inject-h": "^1.4.0",
-        "@vue/babel-sugar-composition-api-render-instance": "^1.4.0",
-        "@vue/babel-sugar-functional-vue": "^1.4.0",
-        "@vue/babel-sugar-inject-h": "^1.4.0",
-        "@vue/babel-sugar-v-model": "^1.4.0",
-        "@vue/babel-sugar-v-on": "^1.4.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0",
-        "vue": "*"
-      },
-      "peerDependenciesMeta": {
-        "vue": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/babel-sugar-composition-api-inject-h": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.4.0.tgz",
-      "integrity": "sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-composition-api-render-instance": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.4.0.tgz",
-      "integrity": "sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-functional-vue": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.4.0.tgz",
-      "integrity": "sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-inject-h": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.4.0.tgz",
-      "integrity": "sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-v-model": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.4.0.tgz",
-      "integrity": "sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0",
-        "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
-        "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
-        "camelcase": "^5.0.0",
-        "html-tags": "^2.0.0",
-        "svg-tags": "^1.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-v-model/node_modules/camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
-      "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@vue/babel-sugar-v-on": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.4.0.tgz",
-      "integrity": "sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==",
-      "dev": true,
-      "dependencies": {
-        "@babel/plugin-syntax-jsx": "^7.2.0",
-        "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
-        "camelcase": "^5.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@vue/babel-sugar-v-on/node_modules/camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@vue/cli-overlay": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.8.tgz",
-      "integrity": "sha512-KmtievE/B4kcXp6SuM2gzsnSd8WebkQpg3XaB6GmFh1BJGRqa1UiW9up7L/Q67uOdTigHxr5Ar2lZms4RcDjwQ==",
-      "dev": true
-    },
-    "node_modules/@vue/cli-plugin-babel": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.8.tgz",
-      "integrity": "sha512-a4qqkml3FAJ3auqB2kN2EMPocb/iu0ykeELwed+9B1c1nQ1HKgslKMHMPavYx3Cd/QAx2mBD4hwKBqZXEI/CsQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/core": "^7.12.16",
-        "@vue/babel-preset-app": "^5.0.8",
-        "@vue/cli-shared-utils": "^5.0.8",
-        "babel-loader": "^8.2.2",
-        "thread-loader": "^3.0.0",
-        "webpack": "^5.54.0"
-      },
-      "peerDependencies": {
-        "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
-      }
-    },
-    "node_modules/@vue/cli-plugin-router": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.8.tgz",
-      "integrity": "sha512-Gmv4dsGdAsWPqVijz3Ux2OS2HkMrWi1ENj2cYL75nUeL+Xj5HEstSqdtfZ0b1q9NCce+BFB6QnHfTBXc/fCvMg==",
-      "dev": true,
-      "dependencies": {
-        "@vue/cli-shared-utils": "^5.0.8"
-      },
-      "peerDependencies": {
-        "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
-      }
-    },
-    "node_modules/@vue/cli-plugin-vuex": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz",
-      "integrity": "sha512-HSYWPqrunRE5ZZs8kVwiY6oWcn95qf/OQabwLfprhdpFWAGtLStShjsGED2aDpSSeGAskQETrtR/5h7VqgIlBA==",
-      "dev": true,
-      "peerDependencies": {
-        "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
-      }
-    },
-    "node_modules/@vue/cli-service": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.8.tgz",
-      "integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.12.16",
-        "@soda/friendly-errors-webpack-plugin": "^1.8.0",
-        "@soda/get-current-script": "^1.0.2",
-        "@types/minimist": "^1.2.0",
-        "@vue/cli-overlay": "^5.0.8",
-        "@vue/cli-plugin-router": "^5.0.8",
-        "@vue/cli-plugin-vuex": "^5.0.8",
-        "@vue/cli-shared-utils": "^5.0.8",
-        "@vue/component-compiler-utils": "^3.3.0",
-        "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7",
-        "@vue/web-component-wrapper": "^1.3.0",
-        "acorn": "^8.0.5",
-        "acorn-walk": "^8.0.2",
-        "address": "^1.1.2",
-        "autoprefixer": "^10.2.4",
-        "browserslist": "^4.16.3",
-        "case-sensitive-paths-webpack-plugin": "^2.3.0",
-        "cli-highlight": "^2.1.10",
-        "clipboardy": "^2.3.0",
-        "cliui": "^7.0.4",
-        "copy-webpack-plugin": "^9.0.1",
-        "css-loader": "^6.5.0",
-        "css-minimizer-webpack-plugin": "^3.0.2",
-        "cssnano": "^5.0.0",
-        "debug": "^4.1.1",
-        "default-gateway": "^6.0.3",
-        "dotenv": "^10.0.0",
-        "dotenv-expand": "^5.1.0",
-        "fs-extra": "^9.1.0",
-        "globby": "^11.0.2",
-        "hash-sum": "^2.0.0",
-        "html-webpack-plugin": "^5.1.0",
-        "is-file-esm": "^1.0.0",
-        "launch-editor-middleware": "^2.2.1",
-        "lodash.defaultsdeep": "^4.6.1",
-        "lodash.mapvalues": "^4.6.0",
-        "mini-css-extract-plugin": "^2.5.3",
-        "minimist": "^1.2.5",
-        "module-alias": "^2.2.2",
-        "portfinder": "^1.0.26",
-        "postcss": "^8.2.6",
-        "postcss-loader": "^6.1.1",
-        "progress-webpack-plugin": "^1.0.12",
-        "ssri": "^8.0.1",
-        "terser-webpack-plugin": "^5.1.1",
-        "thread-loader": "^3.0.0",
-        "vue-loader": "^17.0.0",
-        "vue-style-loader": "^4.1.3",
-        "webpack": "^5.54.0",
-        "webpack-bundle-analyzer": "^4.4.0",
-        "webpack-chain": "^6.5.1",
-        "webpack-dev-server": "^4.7.3",
-        "webpack-merge": "^5.7.3",
-        "webpack-virtual-modules": "^0.4.2",
-        "whatwg-fetch": "^3.6.2"
-      },
-      "bin": {
-        "vue-cli-service": "bin/vue-cli-service.js"
-      },
-      "engines": {
-        "node": "^12.0.0 || >= 14.0.0"
-      },
-      "peerDependencies": {
-        "vue-template-compiler": "^2.0.0",
-        "webpack-sources": "*"
-      },
-      "peerDependenciesMeta": {
-        "cache-loader": {
-          "optional": true
-        },
-        "less-loader": {
-          "optional": true
-        },
-        "pug-plain-loader": {
-          "optional": true
-        },
-        "raw-loader": {
-          "optional": true
-        },
-        "sass-loader": {
-          "optional": true
-        },
-        "stylus-loader": {
-          "optional": true
-        },
-        "vue-template-compiler": {
-          "optional": true
-        },
-        "webpack-sources": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/cli-shared-utils": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.8.tgz",
-      "integrity": "sha512-uK2YB7bBVuQhjOJF+O52P9yFMXeJVj7ozqJkwYE9PlMHL1LMHjtCYm4cSdOebuPzyP+/9p0BimM/OqxsevIopQ==",
-      "dev": true,
-      "dependencies": {
-        "@achrinza/node-ipc": "^9.2.5",
-        "chalk": "^4.1.2",
-        "execa": "^1.0.0",
-        "joi": "^17.4.0",
-        "launch-editor": "^2.2.1",
-        "lru-cache": "^6.0.0",
-        "node-fetch": "^2.6.7",
-        "open": "^8.0.2",
-        "ora": "^5.3.0",
-        "read-pkg": "^5.1.1",
-        "semver": "^7.3.4",
-        "strip-ansi": "^6.0.0"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/semver": {
-      "version": "7.5.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@vue/cli-shared-utils/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/@vue/compiler-sfc": {
-      "version": "2.7.15",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.15.tgz",
-      "integrity": "sha512-FCvIEevPmgCgqFBH7wD+3B97y7u7oj/Wr69zADBf403Tui377bThTjBvekaZvlRr4IwUAu3M6hYZeULZFJbdYg==",
-      "dependencies": {
-        "@babel/parser": "^7.18.4",
-        "postcss": "^8.4.14",
-        "source-map": "^0.6.1"
-      }
-    },
-    "node_modules/@vue/component-compiler-utils": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz",
-      "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==",
-      "dev": true,
-      "dependencies": {
-        "consolidate": "^0.15.1",
-        "hash-sum": "^1.0.2",
-        "lru-cache": "^4.1.2",
-        "merge-source-map": "^1.1.0",
-        "postcss": "^7.0.36",
-        "postcss-selector-parser": "^6.0.2",
-        "source-map": "~0.6.1",
-        "vue-template-es2015-compiler": "^1.9.0"
-      },
-      "optionalDependencies": {
-        "prettier": "^1.18.2 || ^2.0.0"
-      }
-    },
-    "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-      "dev": true
-    },
-    "node_modules/@vue/component-compiler-utils/node_modules/lru-cache": {
-      "version": "4.1.5",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-      "dev": true,
-      "dependencies": {
-        "pseudomap": "^1.0.2",
-        "yallist": "^2.1.2"
-      }
-    },
-    "node_modules/@vue/component-compiler-utils/node_modules/picocolors": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
-      "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
-      "dev": true
-    },
-    "node_modules/@vue/component-compiler-utils/node_modules/postcss": {
-      "version": "7.0.39",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
-      "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
-      "dev": true,
-      "dependencies": {
-        "picocolors": "^0.2.1",
-        "source-map": "^0.6.1"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
-      }
-    },
-    "node_modules/@vue/component-compiler-utils/node_modules/yallist": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-      "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
-      "dev": true
-    },
-    "node_modules/@vue/vue-loader-v15": {
-      "name": "vue-loader",
-      "version": "15.11.1",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz",
-      "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==",
-      "dev": true,
-      "dependencies": {
-        "@vue/component-compiler-utils": "^3.1.0",
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.1.0",
-        "vue-hot-reload-api": "^2.3.0",
-        "vue-style-loader": "^4.1.0"
-      },
-      "peerDependencies": {
-        "css-loader": "*",
-        "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0"
-      },
-      "peerDependenciesMeta": {
-        "cache-loader": {
-          "optional": true
-        },
-        "prettier": {
-          "optional": true
-        },
-        "vue-template-compiler": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-      "dev": true
-    },
-    "node_modules/@vue/web-component-wrapper": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
-      "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/ast": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
-      "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/helper-numbers": "1.11.6",
-        "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/floating-point-hex-parser": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
-      "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/helper-api-error": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
-      "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/helper-buffer": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
-      "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/helper-numbers": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
-      "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/floating-point-hex-parser": "1.11.6",
-        "@webassemblyjs/helper-api-error": "1.11.6",
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
-      "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/helper-wasm-section": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
-      "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@webassemblyjs/helper-buffer": "1.11.6",
-        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
-        "@webassemblyjs/wasm-gen": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/ieee754": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
-      "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
-      "dev": true,
-      "dependencies": {
-        "@xtuc/ieee754": "^1.2.0"
-      }
-    },
-    "node_modules/@webassemblyjs/leb128": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
-      "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
-      "dev": true,
-      "dependencies": {
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "node_modules/@webassemblyjs/utf8": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
-      "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
-      "dev": true
-    },
-    "node_modules/@webassemblyjs/wasm-edit": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
-      "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@webassemblyjs/helper-buffer": "1.11.6",
-        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
-        "@webassemblyjs/helper-wasm-section": "1.11.6",
-        "@webassemblyjs/wasm-gen": "1.11.6",
-        "@webassemblyjs/wasm-opt": "1.11.6",
-        "@webassemblyjs/wasm-parser": "1.11.6",
-        "@webassemblyjs/wast-printer": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/wasm-gen": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
-      "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
-        "@webassemblyjs/ieee754": "1.11.6",
-        "@webassemblyjs/leb128": "1.11.6",
-        "@webassemblyjs/utf8": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/wasm-opt": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
-      "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@webassemblyjs/helper-buffer": "1.11.6",
-        "@webassemblyjs/wasm-gen": "1.11.6",
-        "@webassemblyjs/wasm-parser": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/wasm-parser": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
-      "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@webassemblyjs/helper-api-error": "1.11.6",
-        "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
-        "@webassemblyjs/ieee754": "1.11.6",
-        "@webassemblyjs/leb128": "1.11.6",
-        "@webassemblyjs/utf8": "1.11.6"
-      }
-    },
-    "node_modules/@webassemblyjs/wast-printer": {
-      "version": "1.11.6",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
-      "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
-      "dev": true,
-      "dependencies": {
-        "@webassemblyjs/ast": "1.11.6",
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "node_modules/@xtuc/ieee754": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
-      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
-      "dev": true
-    },
-    "node_modules/@xtuc/long": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
-      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
-      "dev": true
-    },
-    "node_modules/accepts": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "dev": true,
-      "dependencies": {
-        "mime-types": "~2.1.34",
-        "negotiator": "0.6.3"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/acorn": {
-      "version": "8.11.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
-      "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
-      "dev": true,
-      "bin": {
-        "acorn": "bin/acorn"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/acorn-import-assertions": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
-      "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
-      "dev": true,
-      "peerDependencies": {
-        "acorn": "^8"
-      }
-    },
-    "node_modules/acorn-walk": {
-      "version": "8.3.1",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz",
-      "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/address": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz",
-      "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10.0.0"
-      }
-    },
-    "node_modules/ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/ajv-formats": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
-      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
-      "dev": true,
-      "dependencies": {
-        "ajv": "^8.0.0"
-      },
-      "peerDependencies": {
-        "ajv": "^8.0.0"
-      },
-      "peerDependenciesMeta": {
-        "ajv": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/ajv-formats/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/ajv-formats/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/ajv-keywords": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
-      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
-      "dev": true,
-      "peerDependencies": {
-        "ajv": "^6.9.1"
-      }
-    },
-    "node_modules/ansi-escapes": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
-      "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/ansi-html-community": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
-      "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
-      "dev": true,
-      "engines": [
-        "node >= 0.8.0"
-      ],
-      "bin": {
-        "ansi-html": "bin/ansi-html"
-      }
-    },
-    "node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/any-promise": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-      "dev": true
-    },
-    "node_modules/anymatch": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "dev": true,
-      "dependencies": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/arch": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
-      "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/array-flatten": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
-      "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
-      "dev": true
-    },
-    "node_modules/array-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/async": {
-      "version": "2.6.4",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
-      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
-      "dev": true,
-      "dependencies": {
-        "lodash": "^4.17.14"
-      }
-    },
-    "node_modules/async-validator": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
-      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
-      "dependencies": {
-        "babel-runtime": "6.x"
-      }
-    },
-    "node_modules/asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
-    },
-    "node_modules/at-least-node": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
-      "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4.0.0"
-      }
-    },
-    "node_modules/autoprefixer": {
-      "version": "10.4.16",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
-      "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/autoprefixer"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "dependencies": {
-        "browserslist": "^4.21.10",
-        "caniuse-lite": "^1.0.30001538",
-        "fraction.js": "^4.3.6",
-        "normalize-range": "^0.1.2",
-        "picocolors": "^1.0.0",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "bin": {
-        "autoprefixer": "bin/autoprefixer"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/axios": {
-      "version": "1.6.2",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
-      "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
-      "dependencies": {
-        "follow-redirects": "^1.15.0",
-        "form-data": "^4.0.0",
-        "proxy-from-env": "^1.1.0"
-      }
-    },
-    "node_modules/babel-helper-vue-jsx-merge-props": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
-      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
-    },
-    "node_modules/babel-loader": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz",
-      "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==",
-      "dev": true,
-      "dependencies": {
-        "find-cache-dir": "^3.3.1",
-        "loader-utils": "^2.0.0",
-        "make-dir": "^3.1.0",
-        "schema-utils": "^2.6.5"
-      },
-      "engines": {
-        "node": ">= 8.9"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0",
-        "webpack": ">=2"
-      }
-    },
-    "node_modules/babel-loader/node_modules/loader-utils": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-      "dev": true,
-      "dependencies": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^2.1.2"
-      },
-      "engines": {
-        "node": ">=8.9.0"
-      }
-    },
-    "node_modules/babel-plugin-dynamic-import-node": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
-      "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
-      "dev": true,
-      "dependencies": {
-        "object.assign": "^4.1.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-corejs2": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz",
-      "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==",
-      "dev": true,
-      "dependencies": {
-        "@babel/compat-data": "^7.22.6",
-        "@babel/helper-define-polyfill-provider": "^0.4.3",
-        "semver": "^6.3.1"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-corejs3": {
-      "version": "0.8.6",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz",
-      "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.4.3",
-        "core-js-compat": "^3.33.1"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-regenerator": {
-      "version": "0.5.3",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz",
-      "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.4.3"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
-      "dependencies": {
-        "core-js": "^2.4.0",
-        "regenerator-runtime": "^0.11.0"
-      }
-    },
-    "node_modules/babel-runtime/node_modules/core-js": {
-      "version": "2.6.12",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
-      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
-      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
-      "hasInstallScript": true
-    },
-    "node_modules/babel-runtime/node_modules/regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
-    },
-    "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
-    },
-    "node_modules/base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/batch": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-      "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
-      "dev": true
-    },
-    "node_modules/big.js": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
-      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/bl": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
-      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
-      "dev": true,
-      "dependencies": {
-        "buffer": "^5.5.0",
-        "inherits": "^2.0.4",
-        "readable-stream": "^3.4.0"
-      }
-    },
-    "node_modules/bluebird": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
-      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
-      "dev": true
-    },
-    "node_modules/body-parser": {
-      "version": "1.20.1",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
-      "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
-      "dev": true,
-      "dependencies": {
-        "bytes": "3.1.2",
-        "content-type": "~1.0.4",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "on-finished": "2.4.1",
-        "qs": "6.11.0",
-        "raw-body": "2.5.1",
-        "type-is": "~1.6.18",
-        "unpipe": "1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8",
-        "npm": "1.2.8000 || >= 1.4.16"
-      }
-    },
-    "node_modules/body-parser/node_modules/bytes": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/body-parser/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/body-parser/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/bonjour-service": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz",
-      "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==",
-      "dev": true,
-      "dependencies": {
-        "array-flatten": "^2.1.2",
-        "dns-equal": "^1.0.0",
-        "fast-deep-equal": "^3.1.3",
-        "multicast-dns": "^7.2.5"
-      }
-    },
-    "node_modules/boolbase": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
-      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
-      "dev": true
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "dependencies": {
-        "fill-range": "^7.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/browserslist": {
-      "version": "4.22.2",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
-      "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "dependencies": {
-        "caniuse-lite": "^1.0.30001565",
-        "electron-to-chromium": "^1.4.601",
-        "node-releases": "^2.0.14",
-        "update-browserslist-db": "^1.0.13"
-      },
-      "bin": {
-        "browserslist": "cli.js"
-      },
-      "engines": {
-        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-      }
-    },
-    "node_modules/buffer": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "dependencies": {
-        "base64-js": "^1.3.1",
-        "ieee754": "^1.1.13"
-      }
-    },
-    "node_modules/buffer-from": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
-      "dev": true
-    },
-    "node_modules/bytes": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
-      "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/call-bind": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
-      "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
-      "dev": true,
-      "dependencies": {
-        "function-bind": "^1.1.2",
-        "get-intrinsic": "^1.2.1",
-        "set-function-length": "^1.1.1"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/camel-case": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
-      "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
-      "dev": true,
-      "dependencies": {
-        "pascal-case": "^3.1.2",
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/camelcase": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
-      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/caniuse-api": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
-      "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.0.0",
-        "caniuse-lite": "^1.0.0",
-        "lodash.memoize": "^4.1.2",
-        "lodash.uniq": "^4.5.0"
-      }
-    },
-    "node_modules/caniuse-lite": {
-      "version": "1.0.30001566",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz",
-      "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ]
-    },
-    "node_modules/case-sensitive-paths-webpack-plugin": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
-      "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://paulmillr.com/funding/"
-        }
-      ],
-      "dependencies": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      },
-      "engines": {
-        "node": ">= 8.10.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/chokidar/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/chrome-trace-event": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
-      "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.0"
-      }
-    },
-    "node_modules/clean-css": {
-      "version": "5.3.3",
-      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
-      "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
-      "dev": true,
-      "dependencies": {
-        "source-map": "~0.6.0"
-      },
-      "engines": {
-        "node": ">= 10.0"
-      }
-    },
-    "node_modules/cli-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
-      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
-      "dev": true,
-      "dependencies": {
-        "restore-cursor": "^3.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cli-highlight": {
-      "version": "2.1.11",
-      "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
-      "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^4.0.0",
-        "highlight.js": "^10.7.1",
-        "mz": "^2.4.0",
-        "parse5": "^5.1.1",
-        "parse5-htmlparser2-tree-adapter": "^6.0.0",
-        "yargs": "^16.0.0"
-      },
-      "bin": {
-        "highlight": "bin/highlight"
-      },
-      "engines": {
-        "node": ">=8.0.0",
-        "npm": ">=5.0.0"
-      }
-    },
-    "node_modules/cli-highlight/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/cli-highlight/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/cli-highlight/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/cli-highlight/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/cli-highlight/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cli-highlight/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cli-spinners": {
-      "version": "2.9.2",
-      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
-      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/clipboardy": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
-      "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==",
-      "dev": true,
-      "dependencies": {
-        "arch": "^2.1.1",
-        "execa": "^1.0.0",
-        "is-wsl": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cliui": {
-      "version": "7.0.4",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
-      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.0",
-        "wrap-ansi": "^7.0.0"
-      }
-    },
-    "node_modules/clone": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/clone-deep": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
-      "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
-      "dev": true,
-      "dependencies": {
-        "is-plain-object": "^2.0.4",
-        "kind-of": "^6.0.2",
-        "shallow-clone": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/clone-deep/node_modules/is-plain-object": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
-      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
-      "dev": true,
-      "dependencies": {
-        "isobject": "^3.0.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
-    },
-    "node_modules/colord": {
-      "version": "2.9.3",
-      "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
-      "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
-      "dev": true
-    },
-    "node_modules/colorette": {
-      "version": "2.0.20",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
-      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
-      "dev": true
-    },
-    "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==",
-      "dependencies": {
-        "delayed-stream": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/commander": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
-      "dev": true,
-      "engines": {
-        "node": ">= 12"
-      }
-    },
-    "node_modules/commondir": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
-      "dev": true
-    },
-    "node_modules/compressible": {
-      "version": "2.0.18",
-      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
-      "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
-      "dev": true,
-      "dependencies": {
-        "mime-db": ">= 1.43.0 < 2"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/compression": {
-      "version": "1.7.4",
-      "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
-      "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
-      "dev": true,
-      "dependencies": {
-        "accepts": "~1.3.5",
-        "bytes": "3.0.0",
-        "compressible": "~2.0.16",
-        "debug": "2.6.9",
-        "on-headers": "~1.0.2",
-        "safe-buffer": "5.1.2",
-        "vary": "~1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/compression/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/compression/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/compression/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
-    },
-    "node_modules/connect-history-api-fallback": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
-      "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/consolidate": {
-      "version": "0.15.1",
-      "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
-      "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
-      "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog",
-      "dev": true,
-      "dependencies": {
-        "bluebird": "^3.1.1"
-      },
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/content-disposition": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "5.2.1"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/content-type": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
-      "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/convert-source-map": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
-      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
-      "dev": true
-    },
-    "node_modules/cookie": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
-      "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
-      "dev": true
-    },
-    "node_modules/copy-webpack-plugin": {
-      "version": "9.1.0",
-      "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz",
-      "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==",
-      "dev": true,
-      "dependencies": {
-        "fast-glob": "^3.2.7",
-        "glob-parent": "^6.0.1",
-        "globby": "^11.0.3",
-        "normalize-path": "^3.0.0",
-        "schema-utils": "^3.1.1",
-        "serialize-javascript": "^6.0.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^5.1.0"
-      }
-    },
-    "node_modules/copy-webpack-plugin/node_modules/schema-utils": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
-      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.8",
-        "ajv": "^6.12.5",
-        "ajv-keywords": "^3.5.2"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/core-js": {
-      "version": "3.34.0",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.34.0.tgz",
-      "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==",
-      "hasInstallScript": true,
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/core-js"
-      }
-    },
-    "node_modules/core-js-compat": {
-      "version": "3.34.0",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.34.0.tgz",
-      "integrity": "sha512-4ZIyeNbW/Cn1wkMMDy+mvrRUxrwFNjKwbhCfQpDd+eLgYipDqp8oGFGtLmhh18EDPKA0g3VUBYOxQGGwvWLVpA==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.22.2"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/core-js"
-      }
-    },
-    "node_modules/core-util-is": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
-      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
-      "dev": true
-    },
-    "node_modules/cosmiconfig": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
-      "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
-      "dev": true,
-      "dependencies": {
-        "@types/parse-json": "^4.0.0",
-        "import-fresh": "^3.2.1",
-        "parse-json": "^5.0.0",
-        "path-type": "^4.0.0",
-        "yaml": "^1.10.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/cross-spawn": {
-      "version": "6.0.5",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
-      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
-      "dev": true,
-      "dependencies": {
-        "nice-try": "^1.0.4",
-        "path-key": "^2.0.1",
-        "semver": "^5.5.0",
-        "shebang-command": "^1.2.0",
-        "which": "^1.2.9"
-      },
-      "engines": {
-        "node": ">=4.8"
-      }
-    },
-    "node_modules/cross-spawn/node_modules/semver": {
-      "version": "5.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/css-declaration-sorter": {
-      "version": "6.4.1",
-      "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
-      "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.0.9"
-      }
-    },
-    "node_modules/css-loader": {
-      "version": "6.8.1",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz",
-      "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==",
-      "dev": true,
-      "dependencies": {
-        "icss-utils": "^5.1.0",
-        "postcss": "^8.4.21",
-        "postcss-modules-extract-imports": "^3.0.0",
-        "postcss-modules-local-by-default": "^4.0.3",
-        "postcss-modules-scope": "^3.0.0",
-        "postcss-modules-values": "^4.0.0",
-        "postcss-value-parser": "^4.2.0",
-        "semver": "^7.3.8"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^5.0.0"
-      }
-    },
-    "node_modules/css-loader/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/css-loader/node_modules/semver": {
-      "version": "7.5.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/css-loader/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/css-minimizer-webpack-plugin": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz",
-      "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==",
-      "dev": true,
-      "dependencies": {
-        "cssnano": "^5.0.6",
-        "jest-worker": "^27.0.2",
-        "postcss": "^8.3.5",
-        "schema-utils": "^4.0.0",
-        "serialize-javascript": "^6.0.0",
-        "source-map": "^0.6.1"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^5.0.0"
-      },
-      "peerDependenciesMeta": {
-        "@parcel/css": {
-          "optional": true
-        },
-        "clean-css": {
-          "optional": true
-        },
-        "csso": {
-          "optional": true
-        },
-        "esbuild": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
-      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3"
-      },
-      "peerDependencies": {
-        "ajv": "^8.8.2"
-      }
-    },
-    "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
-      "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.9",
-        "ajv": "^8.9.0",
-        "ajv-formats": "^2.1.1",
-        "ajv-keywords": "^5.1.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/css-select": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
-      "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
-      "dev": true,
-      "dependencies": {
-        "boolbase": "^1.0.0",
-        "css-what": "^6.0.1",
-        "domhandler": "^4.3.1",
-        "domutils": "^2.8.0",
-        "nth-check": "^2.0.1"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/fb55"
-      }
-    },
-    "node_modules/css-tree": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
-      "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
-      "dev": true,
-      "dependencies": {
-        "mdn-data": "2.0.14",
-        "source-map": "^0.6.1"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/css-what": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
-      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/fb55"
-      }
-    },
-    "node_modules/cssesc": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
-      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
-      "dev": true,
-      "bin": {
-        "cssesc": "bin/cssesc"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/cssnano": {
-      "version": "5.1.15",
-      "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz",
-      "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==",
-      "dev": true,
-      "dependencies": {
-        "cssnano-preset-default": "^5.2.14",
-        "lilconfig": "^2.0.3",
-        "yaml": "^1.10.2"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/cssnano"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/cssnano-preset-default": {
-      "version": "5.2.14",
-      "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz",
-      "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==",
-      "dev": true,
-      "dependencies": {
-        "css-declaration-sorter": "^6.3.1",
-        "cssnano-utils": "^3.1.0",
-        "postcss-calc": "^8.2.3",
-        "postcss-colormin": "^5.3.1",
-        "postcss-convert-values": "^5.1.3",
-        "postcss-discard-comments": "^5.1.2",
-        "postcss-discard-duplicates": "^5.1.0",
-        "postcss-discard-empty": "^5.1.1",
-        "postcss-discard-overridden": "^5.1.0",
-        "postcss-merge-longhand": "^5.1.7",
-        "postcss-merge-rules": "^5.1.4",
-        "postcss-minify-font-values": "^5.1.0",
-        "postcss-minify-gradients": "^5.1.1",
-        "postcss-minify-params": "^5.1.4",
-        "postcss-minify-selectors": "^5.2.1",
-        "postcss-normalize-charset": "^5.1.0",
-        "postcss-normalize-display-values": "^5.1.0",
-        "postcss-normalize-positions": "^5.1.1",
-        "postcss-normalize-repeat-style": "^5.1.1",
-        "postcss-normalize-string": "^5.1.0",
-        "postcss-normalize-timing-functions": "^5.1.0",
-        "postcss-normalize-unicode": "^5.1.1",
-        "postcss-normalize-url": "^5.1.0",
-        "postcss-normalize-whitespace": "^5.1.1",
-        "postcss-ordered-values": "^5.1.3",
-        "postcss-reduce-initial": "^5.1.2",
-        "postcss-reduce-transforms": "^5.1.0",
-        "postcss-svgo": "^5.1.0",
-        "postcss-unique-selectors": "^5.1.1"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/cssnano-utils": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
-      "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/csso": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz",
-      "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==",
-      "dev": true,
-      "dependencies": {
-        "css-tree": "^1.1.2"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/csstype": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
-      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
-    },
-    "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
-    },
-    "node_modules/debounce": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
-      "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
-      "dev": true
-    },
-    "node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.1.2"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/deepmerge": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
-      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/default-gateway": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
-      "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
-      "dev": true,
-      "dependencies": {
-        "execa": "^5.0.0"
-      },
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/default-gateway/node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/default-gateway/node_modules/execa": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
-      "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^6.0.0",
-        "human-signals": "^2.1.0",
-        "is-stream": "^2.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^4.0.1",
-        "onetime": "^5.1.2",
-        "signal-exit": "^3.0.3",
-        "strip-final-newline": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/default-gateway/node_modules/get-stream": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-      "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/default-gateway/node_modules/is-stream": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
-      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/default-gateway/node_modules/npm-run-path": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
-      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/default-gateway/node_modules/path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/default-gateway/node_modules/shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
-      "dependencies": {
-        "shebang-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/default-gateway/node_modules/shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/default-gateway/node_modules/which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "node-which": "bin/node-which"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/defaults": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
-      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
-      "dev": true,
-      "dependencies": {
-        "clone": "^1.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/define-data-property": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
-      "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
-      "dev": true,
-      "dependencies": {
-        "get-intrinsic": "^1.2.1",
-        "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/define-lazy-prop": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
-      "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/define-properties": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
-      "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
-      "dev": true,
-      "dependencies": {
-        "define-data-property": "^1.0.1",
-        "has-property-descriptors": "^1.0.0",
-        "object-keys": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/depd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/destroy": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8",
-        "npm": "1.2.8000 || >= 1.4.16"
-      }
-    },
-    "node_modules/detect-node": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
-      "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
-      "dev": true
-    },
-    "node_modules/dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "dependencies": {
-        "path-type": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/dns-equal": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
-      "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
-      "dev": true
-    },
-    "node_modules/dns-packet": {
-      "version": "5.6.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
-      "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
-      "dev": true,
-      "dependencies": {
-        "@leichtgewicht/ip-codec": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/dom-converter": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
-      "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
-      "dev": true,
-      "dependencies": {
-        "utila": "~0.4"
-      }
-    },
-    "node_modules/dom-serializer": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
-      "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.2.0",
-        "entities": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
-      }
-    },
-    "node_modules/domelementtype": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
-      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ]
-    },
-    "node_modules/domhandler": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
-      "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
-      "dev": true,
-      "dependencies": {
-        "domelementtype": "^2.2.0"
-      },
-      "engines": {
-        "node": ">= 4"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domhandler?sponsor=1"
-      }
-    },
-    "node_modules/domutils": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
-      "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
-      "dev": true,
-      "dependencies": {
-        "dom-serializer": "^1.0.1",
-        "domelementtype": "^2.2.0",
-        "domhandler": "^4.2.0"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/domutils?sponsor=1"
-      }
-    },
-    "node_modules/dot-case": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
-      "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
-      "dev": true,
-      "dependencies": {
-        "no-case": "^3.0.4",
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/dotenv": {
-      "version": "10.0.0",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
-      "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/dotenv-expand": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
-      "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
-      "dev": true
-    },
-    "node_modules/downloadjs": {
-      "version": "1.4.7",
-      "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
-      "integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q=="
-    },
-    "node_modules/duplexer": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
-      "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
-      "dev": true
-    },
-    "node_modules/easy-stack": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
-      "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/echarts": {
-      "version": "4.9.0",
-      "resolved": "https://registry.npmjs.org/echarts/-/echarts-4.9.0.tgz",
-      "integrity": "sha512-+ugizgtJ+KmsJyyDPxaw2Br5FqzuBnyOWwcxPKO6y0gc5caYcfnEUIlNStx02necw8jmKmTafmpHhGo4XDtEIA==",
-      "dependencies": {
-        "zrender": "4.3.2"
-      }
-    },
-    "node_modules/echarts-amap": {
-      "version": "1.0.0-rc.6",
-      "resolved": "https://registry.npmjs.org/echarts-amap/-/echarts-amap-1.0.0-rc.6.tgz",
-      "integrity": "sha512-cYJCKoQdnkZXrGweYrveU1HruZd1c0KmsF1U8o3FtsvgR2jVL5ZUpGFjMmFtpolHOUFqxizk+s+QBLkYuOWL6Q=="
-    },
-    "node_modules/echarts-liquidfill": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/echarts-liquidfill/-/echarts-liquidfill-2.0.6.tgz",
-      "integrity": "sha512-p+AH0O9/BtwXMQQyhjJbMZo+GwRAgWG/DCyK5r27PQzpS0UWrgXu57MyEFc0A8Ub3sRuqEu08BuxwHICBkSWSQ==",
-      "peerDependencies": {
-        "echarts": "^4.8.0",
-        "zrender": "^4.3.1"
-      }
-    },
-    "node_modules/echarts-wordcloud": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-1.1.3.tgz",
-      "integrity": "sha512-Et8D5xEAoYkidmHun+hEH+2lF9dhCt6D0JJ390vlr2r/1zwhhZAbcL01CEvG93QcMcJpSvSPK8vRiGkTbMHRxg=="
-    },
-    "node_modules/ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-      "dev": true
-    },
-    "node_modules/electron-to-chromium": {
-      "version": "1.4.608",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.608.tgz",
-      "integrity": "sha512-J2f/3iIIm3Mo0npneITZ2UPe4B1bg8fTNrFjD8715F/k1BvbviRuqYGkET1PgprrczXYTHFvotbBOmUp6KE0uA==",
-      "dev": true
-    },
-    "node_modules/element-ui": {
-      "version": "2.15.14",
-      "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.14.tgz",
-      "integrity": "sha512-2v9fHL0ZGINotOlRIAJD5YuVB8V7WKxrE9Qy7dXhRipa035+kF7WuU/z+tEmLVPBcJ0zt8mOu1DKpWcVzBK8IA==",
-      "dependencies": {
-        "async-validator": "~1.8.1",
-        "babel-helper-vue-jsx-merge-props": "^2.0.0",
-        "deepmerge": "^1.2.0",
-        "normalize-wheel": "^1.0.1",
-        "resize-observer-polyfill": "^1.5.0",
-        "throttle-debounce": "^1.0.1"
-      },
-      "peerDependencies": {
-        "vue": "^2.5.17"
-      }
-    },
-    "node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "dev": true
-    },
-    "node_modules/emojis-list": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
-      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/end-of-stream": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
-      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
-      "dev": true,
-      "dependencies": {
-        "once": "^1.4.0"
-      }
-    },
-    "node_modules/enhanced-resolve": {
-      "version": "5.15.0",
-      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
-      "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.2.4",
-        "tapable": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/entities": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
-      "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/fb55/entities?sponsor=1"
-      }
-    },
-    "node_modules/error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-      "dev": true,
-      "dependencies": {
-        "is-arrayish": "^0.2.1"
-      }
-    },
-    "node_modules/error-stack-parser": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
-      "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
-      "dev": true,
-      "dependencies": {
-        "stackframe": "^1.3.4"
-      }
-    },
-    "node_modules/es-module-lexer": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
-      "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==",
-      "dev": true
-    },
-    "node_modules/escalade": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
-      "dev": true
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/eslint-scope": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-      "dev": true,
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^4.1.1"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/esrecurse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-      "dev": true,
-      "dependencies": {
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esrecurse/node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/estraverse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/event-pubsub": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
-      "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/eventemitter3": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
-      "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
-      "dev": true
-    },
-    "node_modules/events": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
-      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.x"
-      }
-    },
-    "node_modules/execa": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
-      "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^6.0.0",
-        "get-stream": "^4.0.0",
-        "is-stream": "^1.1.0",
-        "npm-run-path": "^2.0.0",
-        "p-finally": "^1.0.0",
-        "signal-exit": "^3.0.0",
-        "strip-eof": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/express": {
-      "version": "4.18.2",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
-      "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
-      "dev": true,
-      "dependencies": {
-        "accepts": "~1.3.8",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.20.1",
-        "content-disposition": "0.5.4",
-        "content-type": "~1.0.4",
-        "cookie": "0.5.0",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "finalhandler": "1.2.0",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "merge-descriptors": "1.0.1",
-        "methods": "~1.1.2",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.7",
-        "qs": "6.11.0",
-        "range-parser": "~1.2.1",
-        "safe-buffer": "5.2.1",
-        "send": "0.18.0",
-        "serve-static": "1.15.0",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "type-is": "~1.6.18",
-        "utils-merge": "1.0.1",
-        "vary": "~1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/express/node_modules/array-flatten": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-      "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
-      "dev": true
-    },
-    "node_modules/express/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/express/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-    },
-    "node_modules/fast-glob": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
-      "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      },
-      "engines": {
-        "node": ">=8.6.0"
-      }
-    },
-    "node_modules/fast-glob/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "dev": true
-    },
-    "node_modules/fastq": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
-      "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
-      "dev": true,
-      "dependencies": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "node_modules/faye-websocket": {
-      "version": "0.11.4",
-      "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
-      "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
-      "dev": true,
-      "dependencies": {
-        "websocket-driver": ">=0.5.1"
-      },
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/figures": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
-      "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
-      "dev": true,
-      "dependencies": {
-        "escape-string-regexp": "^1.0.5"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/file-saver": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
-      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
-      "license": "MIT"
-    },
-    "node_modules/fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/finalhandler": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
-      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
-      "dev": true,
-      "dependencies": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "statuses": "2.0.1",
-        "unpipe": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/finalhandler/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/finalhandler/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/find-cache-dir": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
-      "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
-      "dev": true,
-      "dependencies": {
-        "commondir": "^1.0.1",
-        "make-dir": "^3.0.2",
-        "pkg-dir": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
-      }
-    },
-    "node_modules/find-up": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^5.0.0",
-        "path-exists": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/flat": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
-      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
-      "dev": true,
-      "bin": {
-        "flat": "cli.js"
-      }
-    },
-    "node_modules/follow-redirects": {
-      "version": "1.15.3",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
-      "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/RubenVerborgh"
-        }
-      ],
-      "engines": {
-        "node": ">=4.0"
-      },
-      "peerDependenciesMeta": {
-        "debug": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/forwarded": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fraction.js": {
-      "version": "4.3.7",
-      "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
-      "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "type": "patreon",
-        "url": "https://github.com/sponsors/rawify"
-      }
-    },
-    "node_modules/fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fs-extra": {
-      "version": "9.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
-      "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
-      "dev": true,
-      "dependencies": {
-        "at-least-node": "^1.0.0",
-        "graceful-fs": "^4.2.0",
-        "jsonfile": "^6.0.1",
-        "universalify": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/fs-monkey": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz",
-      "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==",
-      "dev": true
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "dev": true
-    },
-    "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,
-      "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==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/gensync": {
-      "version": "1.0.0-beta.2",
-      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
-      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-      "dev": true,
-      "engines": {
-        "node": "6.* || 8.* || >= 10.*"
-      }
-    },
-    "node_modules/get-intrinsic": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
-      "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
-      "dev": true,
-      "dependencies": {
-        "function-bind": "^1.1.2",
-        "has-proto": "^1.0.1",
-        "has-symbols": "^1.0.3",
-        "hasown": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-stream": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
-      "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
-      "dev": true,
-      "dependencies": {
-        "pump": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dev": true,
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/glob-parent": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/glob-to-regexp": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
-      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
-      "dev": true
-    },
-    "node_modules/globals": {
-      "version": "11.12.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/globby": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-      "dev": true,
-      "dependencies": {
-        "array-union": "^2.1.0",
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.2.9",
-        "ignore": "^5.2.0",
-        "merge2": "^1.4.1",
-        "slash": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/gopd": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
-      "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
-      "dev": true,
-      "dependencies": {
-        "get-intrinsic": "^1.1.3"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/graceful-fs": {
-      "version": "4.2.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
-      "dev": true
-    },
-    "node_modules/gzip-size": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
-      "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
-      "dev": true,
-      "dependencies": {
-        "duplexer": "^0.1.2"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/handle-thing": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
-      "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
-      "dev": true
-    },
-    "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/has-property-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
-      "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
-      "dev": true,
-      "dependencies": {
-        "get-intrinsic": "^1.2.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-proto": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
-      "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/has-symbols": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/hash-sum": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
-      "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
-      "dev": true
-    },
-    "node_modules/hasown": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
-      "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
-      "dev": true,
-      "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,
-      "bin": {
-        "he": "bin/he"
-      }
-    },
-    "node_modules/highlight.js": {
-      "version": "10.7.3",
-      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
-      "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/hosted-git-info": {
-      "version": "2.8.9",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
-      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
-      "dev": true
-    },
-    "node_modules/hpack.js": {
-      "version": "2.1.6",
-      "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
-      "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
-      "dev": true,
-      "dependencies": {
-        "inherits": "^2.0.1",
-        "obuf": "^1.0.0",
-        "readable-stream": "^2.0.1",
-        "wbuf": "^1.1.0"
-      }
-    },
-    "node_modules/hpack.js/node_modules/readable-stream": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
-      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
-      "dev": true,
-      "dependencies": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "node_modules/hpack.js/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
-    },
-    "node_modules/hpack.js/node_modules/string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "~5.1.0"
-      }
-    },
-    "node_modules/html-entities": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz",
-      "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/mdevils"
-        },
-        {
-          "type": "patreon",
-          "url": "https://patreon.com/mdevils"
-        }
-      ]
-    },
-    "node_modules/html-escaper": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
-      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
-      "dev": true
-    },
-    "node_modules/html-minifier-terser": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
-      "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
-      "dev": true,
-      "dependencies": {
-        "camel-case": "^4.1.2",
-        "clean-css": "^5.2.2",
-        "commander": "^8.3.0",
-        "he": "^1.2.0",
-        "param-case": "^3.0.4",
-        "relateurl": "^0.2.7",
-        "terser": "^5.10.0"
-      },
-      "bin": {
-        "html-minifier-terser": "cli.js"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/html-tags": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
-      "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/html-webpack-plugin": {
-      "version": "5.5.4",
-      "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.4.tgz",
-      "integrity": "sha512-3wNSaVVxdxcu0jd4FpQFoICdqgxs4zIQQvj+2yQKFfBOnLETQ6X5CDWdeasuGlSsooFlMkEioWDTqBv1wvw5Iw==",
-      "dev": true,
-      "dependencies": {
-        "@types/html-minifier-terser": "^6.0.0",
-        "html-minifier-terser": "^6.0.2",
-        "lodash": "^4.17.21",
-        "pretty-error": "^4.0.0",
-        "tapable": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/html-webpack-plugin"
-      },
-      "peerDependencies": {
-        "webpack": "^5.20.0"
-      }
-    },
-    "node_modules/htmlparser2": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
-      "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
-      "dev": true,
-      "funding": [
-        "https://github.com/fb55/htmlparser2?sponsor=1",
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/fb55"
-        }
-      ],
-      "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^4.0.0",
-        "domutils": "^2.5.2",
-        "entities": "^2.0.0"
-      }
-    },
-    "node_modules/http-deceiver": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
-      "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
-      "dev": true
-    },
-    "node_modules/http-errors": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
-      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-      "dev": true,
-      "dependencies": {
-        "depd": "2.0.0",
-        "inherits": "2.0.4",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "toidentifier": "1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/http-parser-js": {
-      "version": "0.5.8",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
-      "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
-      "dev": true
-    },
-    "node_modules/http-proxy": {
-      "version": "1.18.1",
-      "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
-      "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
-      "dev": true,
-      "dependencies": {
-        "eventemitter3": "^4.0.0",
-        "follow-redirects": "^1.0.0",
-        "requires-port": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/http-proxy-middleware": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
-      "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
-      "dev": true,
-      "dependencies": {
-        "@types/http-proxy": "^1.17.8",
-        "http-proxy": "^1.18.1",
-        "is-glob": "^4.0.1",
-        "is-plain-obj": "^3.0.0",
-        "micromatch": "^4.0.2"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      },
-      "peerDependencies": {
-        "@types/express": "^4.17.13"
-      },
-      "peerDependenciesMeta": {
-        "@types/express": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/human-signals": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
-      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.17.0"
-      }
-    },
-    "node_modules/iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "dev": true,
-      "dependencies": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/icss-utils": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
-      "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >= 14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/ignore": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
-      "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/import-fresh": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
-      "dependencies": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dev": true,
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
-    },
-    "node_modules/ipaddr.js": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz",
-      "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/is-arrayish": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
-      "dev": true
-    },
-    "node_modules/is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "dependencies": {
-        "binary-extensions": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-core-module": {
-      "version": "2.13.1",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
-      "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
-      "dev": true,
-      "dependencies": {
-        "hasown": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-docker": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-      "dev": true,
-      "bin": {
-        "is-docker": "cli.js"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-file-esm": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz",
-      "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==",
-      "dev": true,
-      "dependencies": {
-        "read-pkg-up": "^7.0.1"
-      }
-    },
-    "node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-interactive": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
-      "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/is-plain-obj": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
-      "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-plain-object": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
-      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-unicode-supported": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
-      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-wsl": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
-      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
-      "dev": true,
-      "dependencies": {
-        "is-docker": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
-      "dev": true
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "dev": true
-    },
-    "node_modules/isobject": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-      "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/javascript-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
-      "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==",
-      "dev": true
-    },
-    "node_modules/jest-worker": {
-      "version": "27.5.1",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
-      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*",
-        "merge-stream": "^2.0.0",
-        "supports-color": "^8.0.0"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      }
-    },
-    "node_modules/jest-worker/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-worker/node_modules/supports-color": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
-      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/supports-color?sponsor=1"
-      }
-    },
-    "node_modules/joi": {
-      "version": "17.11.0",
-      "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz",
-      "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==",
-      "dev": true,
-      "dependencies": {
-        "@hapi/hoek": "^9.0.0",
-        "@hapi/topo": "^5.0.0",
-        "@sideway/address": "^4.1.3",
-        "@sideway/formula": "^3.0.1",
-        "@sideway/pinpoint": "^2.0.0"
-      }
-    },
-    "node_modules/js-cookie": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
-      "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/js-message": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
-      "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.6.0"
-      }
-    },
-    "node_modules/js-tokens": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-      "dev": true
-    },
-    "node_modules/jsencrypt": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
-      "integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
-    },
-    "node_modules/jsesc": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-      "dev": true,
-      "bin": {
-        "jsesc": "bin/jsesc"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/json-parse-better-errors": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
-      "dev": true
-    },
-    "node_modules/json-parse-even-better-errors": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
-      "dev": true
-    },
-    "node_modules/json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true
-    },
-    "node_modules/json5": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
-      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
-      "dev": true,
-      "bin": {
-        "json5": "lib/cli.js"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/jsonfile": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
-      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
-      "dev": true,
-      "dependencies": {
-        "universalify": "^2.0.0"
-      },
-      "optionalDependencies": {
-        "graceful-fs": "^4.1.6"
-      }
-    },
-    "node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/klona": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
-      "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/launch-editor": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz",
-      "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==",
-      "dev": true,
-      "dependencies": {
-        "picocolors": "^1.0.0",
-        "shell-quote": "^1.8.1"
-      }
-    },
-    "node_modules/launch-editor-middleware": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.6.1.tgz",
-      "integrity": "sha512-Fg/xYhf7ARmRp40n18wIfJyuAMEjXo67Yull7uF7d0OJ3qA4EYJISt1XfPPn69IIJ5jKgQwzcg6DqHYo95LL/g==",
-      "dev": true,
-      "dependencies": {
-        "launch-editor": "^2.6.1"
-      }
-    },
-    "node_modules/lilconfig": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
-      "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "dev": true
-    },
-    "node_modules/loader-runner": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
-      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.11.5"
-      }
-    },
-    "node_modules/loader-utils": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
-      "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
-      "dev": true,
-      "dependencies": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/loader-utils/node_modules/json5": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
-      "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.0"
-      },
-      "bin": {
-        "json5": "lib/cli.js"
-      }
-    },
-    "node_modules/locate-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-      "dev": true
-    },
-    "node_modules/lodash.debounce": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
-      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
-      "dev": true
-    },
-    "node_modules/lodash.defaultsdeep": {
-      "version": "4.6.1",
-      "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
-      "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
-      "dev": true
-    },
-    "node_modules/lodash.kebabcase": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
-      "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
-      "dev": true
-    },
-    "node_modules/lodash.mapvalues": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz",
-      "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==",
-      "dev": true
-    },
-    "node_modules/lodash.memoize": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-      "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
-      "dev": true
-    },
-    "node_modules/lodash.uniq": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
-      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
-      "dev": true
-    },
-    "node_modules/log-symbols": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
-      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^4.1.0",
-        "is-unicode-supported": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/log-symbols/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/log-symbols/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/log-symbols/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/log-symbols/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/log-symbols/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/log-symbols/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/log-update": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz",
-      "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==",
-      "dev": true,
-      "dependencies": {
-        "ansi-escapes": "^3.0.0",
-        "cli-cursor": "^2.0.0",
-        "wrap-ansi": "^3.0.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/ansi-regex": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
-      "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/cli-cursor": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-      "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
-      "dev": true,
-      "dependencies": {
-        "restore-cursor": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/is-fullwidth-code-point": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
-      "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/mimic-fn": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/onetime": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-      "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/restore-cursor": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-      "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
-      "dev": true,
-      "dependencies": {
-        "onetime": "^2.0.0",
-        "signal-exit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/string-width": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
-      "dev": true,
-      "dependencies": {
-        "is-fullwidth-code-point": "^2.0.0",
-        "strip-ansi": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/strip-ansi": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-      "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/log-update/node_modules/wrap-ansi": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
-      "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^2.1.1",
-        "strip-ansi": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/lower-case": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
-      "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
-      "dev": true,
-      "dependencies": {
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/lru-cache": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^3.0.2"
-      }
-    },
-    "node_modules/make-dir": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
-      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
-      "dev": true,
-      "dependencies": {
-        "semver": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/mdn-data": {
-      "version": "2.0.14",
-      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
-      "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
-      "dev": true
-    },
-    "node_modules/media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/memfs": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
-      "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
-      "dev": true,
-      "dependencies": {
-        "fs-monkey": "^1.0.4"
-      },
-      "engines": {
-        "node": ">= 4.0.0"
-      }
-    },
-    "node_modules/merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
-      "dev": true
-    },
-    "node_modules/merge-source-map": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
-      "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
-      "dev": true,
-      "dependencies": {
-        "source-map": "^0.6.1"
-      }
-    },
-    "node_modules/merge-stream": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
-      "dev": true
-    },
-    "node_modules/merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/micromatch": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
-      "dev": true,
-      "dependencies": {
-        "braces": "^3.0.2",
-        "picomatch": "^2.3.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "dev": true,
-      "bin": {
-        "mime": "cli.js"
-      },
-      "engines": {
-        "node": ">=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==",
-      "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==",
-      "dependencies": {
-        "mime-db": "1.52.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mimic-fn": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/mini-css-extract-plugin": {
-      "version": "2.7.6",
-      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz",
-      "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==",
-      "dev": true,
-      "dependencies": {
-        "schema-utils": "^4.0.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^5.0.0"
-      }
-    },
-    "node_modules/mini-css-extract-plugin/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
-      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3"
-      },
-      "peerDependencies": {
-        "ajv": "^8.8.2"
-      }
-    },
-    "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/mini-css-extract-plugin/node_modules/schema-utils": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
-      "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.9",
-        "ajv": "^8.9.0",
-        "ajv-formats": "^2.1.1",
-        "ajv-keywords": "^5.1.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/minimalistic-assert": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
-      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
-      "dev": true
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/minimist": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/minipass": {
-      "version": "3.3.6",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
-      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/minipass/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/mkdirp": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
-      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
-      "dev": true,
-      "dependencies": {
-        "minimist": "^1.2.6"
-      },
-      "bin": {
-        "mkdirp": "bin/cmd.js"
-      }
-    },
-    "node_modules/module-alias": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz",
-      "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
-      "dev": true
-    },
-    "node_modules/mrmime": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
-      "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
-    },
-    "node_modules/multicast-dns": {
-      "version": "7.2.5",
-      "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
-      "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
-      "dev": true,
-      "dependencies": {
-        "dns-packet": "^5.2.2",
-        "thunky": "^1.0.2"
-      },
-      "bin": {
-        "multicast-dns": "cli.js"
-      }
-    },
-    "node_modules/mz": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
-      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-      "dev": true,
-      "dependencies": {
-        "any-promise": "^1.0.0",
-        "object-assign": "^4.0.1",
-        "thenify-all": "^1.0.0"
-      }
-    },
-    "node_modules/nanoid": {
-      "version": "3.3.7",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
-      "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
-    "node_modules/negotiator": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/neo-async": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
-      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
-      "dev": true
-    },
-    "node_modules/nice-try": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
-      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
-      "dev": true
-    },
-    "node_modules/no-case": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
-      "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
-      "dev": true,
-      "dependencies": {
-        "lower-case": "^2.0.2",
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/node-fetch": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
-      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
-      "dev": true,
-      "dependencies": {
-        "whatwg-url": "^5.0.0"
-      },
-      "engines": {
-        "node": "4.x || >=6.0.0"
-      },
-      "peerDependencies": {
-        "encoding": "^0.1.0"
-      },
-      "peerDependenciesMeta": {
-        "encoding": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/node-forge": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
-      "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 6.13.0"
-      }
-    },
-    "node_modules/node-releases": {
-      "version": "2.0.14",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
-      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
-      "dev": true
-    },
-    "node_modules/normalize-package-data": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
-      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
-      "dev": true,
-      "dependencies": {
-        "hosted-git-info": "^2.1.4",
-        "resolve": "^1.10.0",
-        "semver": "2 || 3 || 4 || 5",
-        "validate-npm-package-license": "^3.0.1"
-      }
-    },
-    "node_modules/normalize-package-data/node_modules/semver": {
-      "version": "5.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/normalize-range": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
-      "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/normalize-url": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
-      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/normalize-wheel": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
-      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
-    },
-    "node_modules/npm-run-path": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
-      "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/nth-check": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
-      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
-      "dev": true,
-      "dependencies": {
-        "boolbase": "^1.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/fb55/nth-check?sponsor=1"
-      }
-    },
-    "node_modules/numerify": {
-      "version": "1.2.9",
-      "resolved": "https://registry.npmjs.org/numerify/-/numerify-1.2.9.tgz",
-      "integrity": "sha512-X4QzQiytV5ZN3TVLhzbtFzjTarUNnaa1pgNDFqt7u7Nqhxe7FvY2eYrGt4WYHlYXDqgtfC/n/a5nJ2y0LijV8w=="
-    },
-    "node_modules/object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/object-inspect": {
-      "version": "1.13.1",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
-      "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/object-keys": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/object.assign": {
-      "version": "4.1.5",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
-      "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.5",
-        "define-properties": "^1.2.1",
-        "has-symbols": "^1.0.3",
-        "object-keys": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/obuf": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
-      "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
-      "dev": true
-    },
-    "node_modules/on-finished": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "dev": true,
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/on-headers": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
-      "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dev": true,
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/onetime": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/open": {
-      "version": "8.4.2",
-      "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
-      "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
-      "dev": true,
-      "dependencies": {
-        "define-lazy-prop": "^2.0.0",
-        "is-docker": "^2.1.1",
-        "is-wsl": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/opener": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
-      "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
-      "dev": true,
-      "bin": {
-        "opener": "bin/opener-bin.js"
-      }
-    },
-    "node_modules/ora": {
-      "version": "5.4.1",
-      "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
-      "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
-      "dev": true,
-      "dependencies": {
-        "bl": "^4.1.0",
-        "chalk": "^4.1.0",
-        "cli-cursor": "^3.1.0",
-        "cli-spinners": "^2.5.0",
-        "is-interactive": "^1.0.0",
-        "is-unicode-supported": "^0.1.0",
-        "log-symbols": "^4.1.0",
-        "strip-ansi": "^6.0.0",
-        "wcwidth": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ora/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/ora/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/ora/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/ora/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/ora/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ora/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/p-finally": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
-      "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-      "dev": true,
-      "dependencies": {
-        "p-try": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-locate": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/p-retry": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
-      "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/retry": "0.12.0",
-        "retry": "^0.13.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/p-try": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/param-case": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
-      "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
-      "dev": true,
-      "dependencies": {
-        "dot-case": "^3.0.4",
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "dependencies": {
-        "callsites": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/parse-json": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
-      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.0.0",
-        "error-ex": "^1.3.1",
-        "json-parse-even-better-errors": "^2.3.0",
-        "lines-and-columns": "^1.1.6"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/parse5": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
-      "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
-      "dev": true
-    },
-    "node_modules/parse5-htmlparser2-tree-adapter": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
-      "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
-      "dev": true,
-      "dependencies": {
-        "parse5": "^6.0.1"
-      }
-    },
-    "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
-      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
-      "dev": true
-    },
-    "node_modules/parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/pascal-case": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
-      "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
-      "dev": true,
-      "dependencies": {
-        "no-case": "^3.0.4",
-        "tslib": "^2.0.3"
-      }
-    },
-    "node_modules/path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/path-key": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
-      "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "dev": true
-    },
-    "node_modules/path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
-      "dev": true
-    },
-    "node_modules/path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/picocolors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
-    },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/pkg-dir": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
-      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
-      "dev": true,
-      "dependencies": {
-        "find-up": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/portfinder": {
-      "version": "1.0.32",
-      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
-      "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==",
-      "dev": true,
-      "dependencies": {
-        "async": "^2.6.4",
-        "debug": "^3.2.7",
-        "mkdirp": "^0.5.6"
-      },
-      "engines": {
-        "node": ">= 0.12.0"
-      }
-    },
-    "node_modules/portfinder/node_modules/debug": {
-      "version": "3.2.7",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-      "dev": true,
-      "dependencies": {
-        "ms": "^2.1.1"
-      }
-    },
-    "node_modules/postcss": {
-      "version": "8.4.32",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz",
-      "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
-      "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"
-        }
-      ],
-      "dependencies": {
-        "nanoid": "^3.3.7",
-        "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.2"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      }
-    },
-    "node_modules/postcss-calc": {
-      "version": "8.2.4",
-      "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz",
-      "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==",
-      "dev": true,
-      "dependencies": {
-        "postcss-selector-parser": "^6.0.9",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.2"
-      }
-    },
-    "node_modules/postcss-colormin": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz",
-      "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "caniuse-api": "^3.0.0",
-        "colord": "^2.9.1",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-convert-values": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz",
-      "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-discard-comments": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
-      "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-discard-duplicates": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
-      "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-discard-empty": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
-      "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-discard-overridden": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
-      "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-loader": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz",
-      "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==",
-      "dev": true,
-      "dependencies": {
-        "cosmiconfig": "^7.0.0",
-        "klona": "^2.0.5",
-        "semver": "^7.3.5"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "postcss": "^7.0.0 || ^8.0.1",
-        "webpack": "^5.0.0"
-      }
-    },
-    "node_modules/postcss-loader/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/postcss-loader/node_modules/semver": {
-      "version": "7.5.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/postcss-loader/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/postcss-merge-longhand": {
-      "version": "5.1.7",
-      "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz",
-      "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0",
-        "stylehacks": "^5.1.1"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-merge-rules": {
-      "version": "5.1.4",
-      "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz",
-      "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "caniuse-api": "^3.0.0",
-        "cssnano-utils": "^3.1.0",
-        "postcss-selector-parser": "^6.0.5"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-minify-font-values": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz",
-      "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-minify-gradients": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz",
-      "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==",
-      "dev": true,
-      "dependencies": {
-        "colord": "^2.9.1",
-        "cssnano-utils": "^3.1.0",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-minify-params": {
-      "version": "5.1.4",
-      "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz",
-      "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "cssnano-utils": "^3.1.0",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-minify-selectors": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz",
-      "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==",
-      "dev": true,
-      "dependencies": {
-        "postcss-selector-parser": "^6.0.5"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-modules-extract-imports": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
-      "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >= 14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/postcss-modules-local-by-default": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz",
-      "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==",
-      "dev": true,
-      "dependencies": {
-        "icss-utils": "^5.0.0",
-        "postcss-selector-parser": "^6.0.2",
-        "postcss-value-parser": "^4.1.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >= 14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/postcss-modules-scope": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
-      "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
-      "dev": true,
-      "dependencies": {
-        "postcss-selector-parser": "^6.0.4"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >= 14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/postcss-modules-values": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
-      "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
-      "dev": true,
-      "dependencies": {
-        "icss-utils": "^5.0.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >= 14"
-      },
-      "peerDependencies": {
-        "postcss": "^8.1.0"
-      }
-    },
-    "node_modules/postcss-normalize-charset": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
-      "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
-      "dev": true,
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-display-values": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz",
-      "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-positions": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz",
-      "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-repeat-style": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz",
-      "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-string": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz",
-      "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-timing-functions": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz",
-      "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-unicode": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz",
-      "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-url": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz",
-      "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==",
-      "dev": true,
-      "dependencies": {
-        "normalize-url": "^6.0.1",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-normalize-whitespace": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz",
-      "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-ordered-values": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz",
-      "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==",
-      "dev": true,
-      "dependencies": {
-        "cssnano-utils": "^3.1.0",
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-reduce-initial": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz",
-      "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "caniuse-api": "^3.0.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-reduce-transforms": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz",
-      "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-selector-parser": {
-      "version": "6.0.13",
-      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
-      "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
-      "dev": true,
-      "dependencies": {
-        "cssesc": "^3.0.0",
-        "util-deprecate": "^1.0.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/postcss-svgo": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz",
-      "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==",
-      "dev": true,
-      "dependencies": {
-        "postcss-value-parser": "^4.2.0",
-        "svgo": "^2.7.0"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-unique-selectors": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz",
-      "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==",
-      "dev": true,
-      "dependencies": {
-        "postcss-selector-parser": "^6.0.5"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/postcss-value-parser": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
-      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
-      "dev": true
-    },
-    "node_modules/prettier": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
-      "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
-      "dev": true,
-      "optional": true,
-      "bin": {
-        "prettier": "bin-prettier.js"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      },
-      "funding": {
-        "url": "https://github.com/prettier/prettier?sponsor=1"
-      }
-    },
-    "node_modules/pretty-error": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
-      "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
-      "dev": true,
-      "dependencies": {
-        "lodash": "^4.17.20",
-        "renderkid": "^3.0.0"
-      }
-    },
-    "node_modules/process-nextick-args": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-      "dev": true
-    },
-    "node_modules/progress-webpack-plugin": {
-      "version": "1.0.16",
-      "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.16.tgz",
-      "integrity": "sha512-sdiHuuKOzELcBANHfrupYo+r99iPRyOnw15qX+rNlVUqXGfjXdH4IgxriKwG1kNJwVswKQHMdj1hYZMcb9jFaA==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^2.1.0",
-        "figures": "^2.0.0",
-        "log-update": "^2.3.0"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "peerDependencies": {
-        "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"
-      }
-    },
-    "node_modules/proxy-addr": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "dev": true,
-      "dependencies": {
-        "forwarded": "0.2.0",
-        "ipaddr.js": "1.9.1"
-      },
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/proxy-addr/node_modules/ipaddr.js": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "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=="
-    },
-    "node_modules/pseudomap": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
-      "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
-      "dev": true
-    },
-    "node_modules/pump": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
-      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
-      "dev": true,
-      "dependencies": {
-        "end-of-stream": "^1.1.0",
-        "once": "^1.3.1"
-      }
-    },
-    "node_modules/punycode": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/qs": {
-      "version": "6.11.0",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
-      "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
-      "dev": true,
-      "dependencies": {
-        "side-channel": "^1.0.4"
-      },
-      "engines": {
-        "node": ">=0.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/randombytes": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
-      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "^5.1.0"
-      }
-    },
-    "node_modules/range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/raw-body": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
-      "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
-      "dev": true,
-      "dependencies": {
-        "bytes": "3.1.2",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "unpipe": "1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/raw-body/node_modules/bytes": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/read-pkg": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
-      "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
-      "dev": true,
-      "dependencies": {
-        "@types/normalize-package-data": "^2.4.0",
-        "normalize-package-data": "^2.5.0",
-        "parse-json": "^5.0.0",
-        "type-fest": "^0.6.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg-up": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
-      "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
-      "dev": true,
-      "dependencies": {
-        "find-up": "^4.1.0",
-        "read-pkg": "^5.2.0",
-        "type-fest": "^0.8.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/type-fest": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "dev": true,
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "dependencies": {
-        "picomatch": "^2.2.1"
-      },
-      "engines": {
-        "node": ">=8.10.0"
-      }
-    },
-    "node_modules/regenerate": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
-      "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
-      "dev": true
-    },
-    "node_modules/regenerate-unicode-properties": {
-      "version": "10.1.1",
-      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz",
-      "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==",
-      "dev": true,
-      "dependencies": {
-        "regenerate": "^1.4.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/regenerator-runtime": {
-      "version": "0.14.0",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
-      "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
-      "dev": true
-    },
-    "node_modules/regenerator-transform": {
-      "version": "0.15.2",
-      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
-      "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/runtime": "^7.8.4"
-      }
-    },
-    "node_modules/regexpu-core": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
-      "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
-      "dev": true,
-      "dependencies": {
-        "@babel/regjsgen": "^0.8.0",
-        "regenerate": "^1.4.2",
-        "regenerate-unicode-properties": "^10.1.0",
-        "regjsparser": "^0.9.1",
-        "unicode-match-property-ecmascript": "^2.0.0",
-        "unicode-match-property-value-ecmascript": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/regjsparser": {
-      "version": "0.9.1",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
-      "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
-      "dev": true,
-      "dependencies": {
-        "jsesc": "~0.5.0"
-      },
-      "bin": {
-        "regjsparser": "bin/parser"
-      }
-    },
-    "node_modules/regjsparser/node_modules/jsesc": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
-      "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
-      "dev": true,
-      "bin": {
-        "jsesc": "bin/jsesc"
-      }
-    },
-    "node_modules/relateurl": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
-      "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/renderkid": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
-      "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
-      "dev": true,
-      "dependencies": {
-        "css-select": "^4.1.3",
-        "dom-converter": "^0.2.0",
-        "htmlparser2": "^6.1.0",
-        "lodash": "^4.17.21",
-        "strip-ansi": "^6.0.1"
-      }
-    },
-    "node_modules/require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/require-from-string": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/requires-port": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
-      "dev": true
-    },
-    "node_modules/resize-observer-polyfill": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
-      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
-    },
-    "node_modules/resolve": {
-      "version": "1.22.8",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
-      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
-      "dev": true,
-      "dependencies": {
-        "is-core-module": "^2.13.0",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      },
-      "bin": {
-        "resolve": "bin/resolve"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/restore-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
-      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
-      "dev": true,
-      "dependencies": {
-        "onetime": "^5.1.0",
-        "signal-exit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/retry": {
-      "version": "0.13.1",
-      "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
-      "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true,
-      "engines": {
-        "iojs": ">=1.0.0",
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "dependencies": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
-    },
-    "node_modules/schema-utils": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
-      "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.5",
-        "ajv": "^6.12.4",
-        "ajv-keywords": "^3.5.2"
-      },
-      "engines": {
-        "node": ">= 8.9.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/select-hose": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-      "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
-      "dev": true
-    },
-    "node_modules/selfsigned": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
-      "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
-      "dev": true,
-      "dependencies": {
-        "@types/node-forge": "^1.3.0",
-        "node-forge": "^1"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/send": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
-      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
-      "dev": true,
-      "dependencies": {
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "2.4.1",
-        "range-parser": "~1.2.1",
-        "statuses": "2.0.1"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/send/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/send/node_modules/debug/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/send/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "dev": true
-    },
-    "node_modules/serialize-javascript": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
-      "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
-      "dev": true,
-      "dependencies": {
-        "randombytes": "^2.1.0"
-      }
-    },
-    "node_modules/serve-index": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-      "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
-      "dev": true,
-      "dependencies": {
-        "accepts": "~1.3.4",
-        "batch": "0.6.1",
-        "debug": "2.6.9",
-        "escape-html": "~1.0.3",
-        "http-errors": "~1.6.2",
-        "mime-types": "~2.1.17",
-        "parseurl": "~1.3.2"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/serve-index/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/serve-index/node_modules/depd": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
-      "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/serve-index/node_modules/http-errors": {
-      "version": "1.6.3",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
-      "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
-      "dev": true,
-      "dependencies": {
-        "depd": "~1.1.2",
-        "inherits": "2.0.3",
-        "setprototypeof": "1.1.0",
-        "statuses": ">= 1.4.0 < 2"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/serve-index/node_modules/inherits": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
-      "dev": true
-    },
-    "node_modules/serve-index/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "dev": true
-    },
-    "node_modules/serve-index/node_modules/setprototypeof": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
-      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
-      "dev": true
-    },
-    "node_modules/serve-index/node_modules/statuses": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/serve-static": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
-      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
-      "dev": true,
-      "dependencies": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "0.18.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/set-function-length": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
-      "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
-      "dev": true,
-      "dependencies": {
-        "define-data-property": "^1.1.1",
-        "get-intrinsic": "^1.2.1",
-        "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-      "dev": true
-    },
-    "node_modules/shallow-clone": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
-      "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
-      "dev": true,
-      "dependencies": {
-        "kind-of": "^6.0.2"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shebang-command": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
-      "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
-      "dev": true,
-      "dependencies": {
-        "shebang-regex": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
-      "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/shell-quote": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
-      "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/side-channel": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.0",
-        "get-intrinsic": "^1.0.2",
-        "object-inspect": "^1.9.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/signal-exit": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
-      "dev": true
-    },
-    "node_modules/sirv": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz",
-      "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==",
-      "dev": true,
-      "dependencies": {
-        "@polka/url": "^1.0.0-next.20",
-        "mrmime": "^1.0.0",
-        "totalist": "^3.0.0"
-      },
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/sockjs": {
-      "version": "0.3.24",
-      "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
-      "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
-      "dev": true,
-      "dependencies": {
-        "faye-websocket": "^0.11.3",
-        "uuid": "^8.3.2",
-        "websocket-driver": "^0.7.4"
-      }
-    },
-    "node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/source-map-js": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
-      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/source-map-support": {
-      "version": "0.5.21",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-      "dev": true,
-      "dependencies": {
-        "buffer-from": "^1.0.0",
-        "source-map": "^0.6.0"
-      }
-    },
-    "node_modules/spdx-correct": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
-      "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
-      "dev": true,
-      "dependencies": {
-        "spdx-expression-parse": "^3.0.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-exceptions": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
-      "dev": true
-    },
-    "node_modules/spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
-      "dev": true,
-      "dependencies": {
-        "spdx-exceptions": "^2.1.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-license-ids": {
-      "version": "3.0.16",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
-      "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
-      "dev": true
-    },
-    "node_modules/spdy": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
-      "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
-      "dev": true,
-      "dependencies": {
-        "debug": "^4.1.0",
-        "handle-thing": "^2.0.0",
-        "http-deceiver": "^1.2.7",
-        "select-hose": "^2.0.0",
-        "spdy-transport": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/spdy-transport": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
-      "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
-      "dev": true,
-      "dependencies": {
-        "debug": "^4.1.0",
-        "detect-node": "^2.0.4",
-        "hpack.js": "^2.1.6",
-        "obuf": "^1.1.2",
-        "readable-stream": "^3.0.6",
-        "wbuf": "^1.7.3"
-      }
-    },
-    "node_modules/ssri": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
-      "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
-      "dev": true,
-      "dependencies": {
-        "minipass": "^3.1.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/stable": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
-      "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
-      "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
-      "dev": true
-    },
-    "node_modules/stackframe": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
-      "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
-      "dev": true
-    },
-    "node_modules/statuses": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
-      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "~5.2.0"
-      }
-    },
-    "node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-eof": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
-      "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/strip-final-newline": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
-      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/stylehacks": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
-      "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==",
-      "dev": true,
-      "dependencies": {
-        "browserslist": "^4.21.4",
-        "postcss-selector-parser": "^6.0.4"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.2.15"
-      }
-    },
-    "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/svg-tags": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
-      "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
-      "dev": true
-    },
-    "node_modules/svgo": {
-      "version": "2.8.0",
-      "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz",
-      "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==",
-      "dev": true,
-      "dependencies": {
-        "@trysound/sax": "0.2.0",
-        "commander": "^7.2.0",
-        "css-select": "^4.1.3",
-        "css-tree": "^1.1.3",
-        "csso": "^4.2.0",
-        "picocolors": "^1.0.0",
-        "stable": "^0.1.8"
-      },
-      "bin": {
-        "svgo": "bin/svgo"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/svgo/node_modules/commander": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
-      "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/tapable": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
-      "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/terser": {
-      "version": "5.26.0",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz",
-      "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/source-map": "^0.3.3",
-        "acorn": "^8.8.2",
-        "commander": "^2.20.0",
-        "source-map-support": "~0.5.20"
-      },
-      "bin": {
-        "terser": "bin/terser"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/terser-webpack-plugin": {
-      "version": "5.3.9",
-      "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
-      "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
-      "dev": true,
-      "dependencies": {
-        "@jridgewell/trace-mapping": "^0.3.17",
-        "jest-worker": "^27.4.5",
-        "schema-utils": "^3.1.1",
-        "serialize-javascript": "^6.0.1",
-        "terser": "^5.16.8"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^5.1.0"
-      },
-      "peerDependenciesMeta": {
-        "@swc/core": {
-          "optional": true
-        },
-        "esbuild": {
-          "optional": true
-        },
-        "uglify-js": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
-      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.8",
-        "ajv": "^6.12.5",
-        "ajv-keywords": "^3.5.2"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/terser/node_modules/commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-      "dev": true
-    },
-    "node_modules/thenify": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
-      "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-      "dev": true,
-      "dependencies": {
-        "any-promise": "^1.0.0"
-      }
-    },
-    "node_modules/thenify-all": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
-      "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-      "dev": true,
-      "dependencies": {
-        "thenify": ">= 3.1.0 < 4"
-      },
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/thread-loader": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz",
-      "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==",
-      "dev": true,
-      "dependencies": {
-        "json-parse-better-errors": "^1.0.2",
-        "loader-runner": "^4.1.0",
-        "loader-utils": "^2.0.0",
-        "neo-async": "^2.6.2",
-        "schema-utils": "^3.0.0"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^4.27.0 || ^5.0.0"
-      }
-    },
-    "node_modules/thread-loader/node_modules/loader-utils": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-      "dev": true,
-      "dependencies": {
-        "big.js": "^5.2.2",
-        "emojis-list": "^3.0.0",
-        "json5": "^2.1.2"
-      },
-      "engines": {
-        "node": ">=8.9.0"
-      }
-    },
-    "node_modules/thread-loader/node_modules/schema-utils": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
-      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.8",
-        "ajv": "^6.12.5",
-        "ajv-keywords": "^3.5.2"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/throttle-debounce": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
-      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/thunky": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
-      "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
-      "dev": true
-    },
-    "node_modules/to-fast-properties": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
-    "node_modules/toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
-    "node_modules/totalist": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
-      "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
-      "dev": true
-    },
-    "node_modules/tslib": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
-      "dev": true
-    },
-    "node_modules/type-fest": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
-      "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/type-is": {
-      "version": "1.6.18",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "dev": true,
-      "dependencies": {
-        "media-typer": "0.3.0",
-        "mime-types": "~2.1.24"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/undici-types": {
-      "version": "5.26.5",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
-      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
-      "dev": true
-    },
-    "node_modules/unicode-canonical-property-names-ecmascript": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
-      "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-match-property-ecmascript": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
-      "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
-      "dev": true,
-      "dependencies": {
-        "unicode-canonical-property-names-ecmascript": "^2.0.0",
-        "unicode-property-aliases-ecmascript": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-match-property-value-ecmascript": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
-      "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-property-aliases-ecmascript": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
-      "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/universalify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
-      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10.0.0"
-      }
-    },
-    "node_modules/unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/update-browserslist-db": {
-      "version": "1.0.13",
-      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
-      "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "dependencies": {
-        "escalade": "^3.1.1",
-        "picocolors": "^1.0.0"
-      },
-      "bin": {
-        "update-browserslist-db": "cli.js"
-      },
-      "peerDependencies": {
-        "browserslist": ">= 4.21.0"
-      }
-    },
-    "node_modules/uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-      "dev": true,
-      "dependencies": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "node_modules/util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "dev": true
-    },
-    "node_modules/utila": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
-      "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
-      "dev": true
-    },
-    "node_modules/utils-lite": {
-      "version": "0.1.10",
-      "resolved": "https://registry.npmjs.org/utils-lite/-/utils-lite-0.1.10.tgz",
-      "integrity": "sha512-jlHvdtI8MyWURF/3u+ufIjf1Cs5WjN6WZl9qO8dEkZsVjaI7X5YMUhaCFzkvB69ljt6fo4Dd7V/Oj2NJOFDFOQ=="
-    },
-    "node_modules/utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/uuid": {
-      "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-      "dev": true,
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/v-charts": {
-      "version": "1.19.0",
-      "resolved": "https://registry.npmjs.org/v-charts/-/v-charts-1.19.0.tgz",
-      "integrity": "sha512-vm2HBUmxAsXK0ivwce9LytcpqrItDA5JSPLYVxZXtiuoyhcn80XX1/3dPJd/1GqG1OYv3jfBo1s9ra4q8GowqA==",
-      "dependencies": {
-        "echarts-amap": "1.0.0-rc.6",
-        "echarts-liquidfill": "^2.0.2",
-        "echarts-wordcloud": "^1.1.3",
-        "numerify": "1.2.9",
-        "utils-lite": "0.1.10"
-      },
-      "peerDependencies": {
-        "echarts": ">3.0.0",
-        "vue": ">2.0.0"
-      }
-    },
-    "node_modules/validate-npm-package-license": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
-      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
-      "dev": true,
-      "dependencies": {
-        "spdx-correct": "^3.0.0",
-        "spdx-expression-parse": "^3.0.0"
-      }
-    },
-    "node_modules/vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/vue": {
-      "version": "2.7.15",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.15.tgz",
-      "integrity": "sha512-a29fsXd2G0KMRqIFTpRgpSbWaNBK3lpCTOLuGLEDnlHWdjB8fwl6zyYZ8xCrqkJdatwZb4mGHiEfJjnw0Q6AwQ==",
-      "dependencies": {
-        "@vue/compiler-sfc": "2.7.15",
-        "csstype": "^3.1.0"
-      }
-    },
-    "node_modules/vue-hot-reload-api": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
-      "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
-      "dev": true
-    },
-    "node_modules/vue-i18n": {
-      "version": "7.3.2",
-      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-7.3.2.tgz",
-      "integrity": "sha512-4NBhqrH4Pe1etecC2aafXEKH9gJY+TaO4EHYZ0EBYPwFakUp4FyDHHf+r2N1keSX60iEm1k25WcVMD+OxAH/yw=="
-    },
-    "node_modules/vue-json-excel": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/vue-json-excel/-/vue-json-excel-0.3.0.tgz",
-      "integrity": "sha512-FrSh0tVUpw4K+ilLO8g0Qp52eFJw/hkk3rZPTEKo9qVkJgVfQtZwzj3UWc5ACYxA3jLk9HtjK+f9xKHCN4Kgag==",
-      "dependencies": {
-        "downloadjs": "^1.4.7"
-      }
-    },
-    "node_modules/vue-loader": {
-      "version": "17.3.1",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.3.1.tgz",
-      "integrity": "sha512-nmVu7KU8geOyzsStyyaxID/uBGDMS8BkPXb6Lu2SNkMawriIbb+hYrNtgftHMKxOSkjjjTF5OSSwPo3KP59egg==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "watchpack": "^2.4.0"
-      },
-      "peerDependencies": {
-        "webpack": "^4.1.0 || ^5.0.0-0"
-      },
-      "peerDependenciesMeta": {
-        "@vue/compiler-sfc": {
-          "optional": true
-        },
-        "vue": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/vue-loader/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/vue-loader/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/vue-loader/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/vue-loader/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/vue-loader/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/vue-loader/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/vue-router": {
-      "version": "3.6.5",
-      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.6.5.tgz",
-      "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ=="
-    },
-    "node_modules/vue-style-loader": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
-      "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==",
-      "dev": true,
-      "dependencies": {
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.0.2"
-      }
-    },
-    "node_modules/vue-style-loader/node_modules/hash-sum": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-      "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
-      "dev": true
-    },
-    "node_modules/vue-template-compiler": {
-      "version": "2.7.15",
-      "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz",
-      "integrity": "sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==",
-      "dev": true,
-      "dependencies": {
-        "de-indent": "^1.0.2",
-        "he": "^1.2.0"
-      }
-    },
-    "node_modules/vue-template-es2015-compiler": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
-      "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
-      "dev": true
-    },
-    "node_modules/watchpack": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
-      "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
-      "dev": true,
-      "dependencies": {
-        "glob-to-regexp": "^0.4.1",
-        "graceful-fs": "^4.1.2"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/wbuf": {
-      "version": "1.7.3",
-      "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
-      "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
-      "dev": true,
-      "dependencies": {
-        "minimalistic-assert": "^1.0.0"
-      }
-    },
-    "node_modules/wcwidth": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
-      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
-      "dev": true,
-      "dependencies": {
-        "defaults": "^1.0.3"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
-      "dev": true
-    },
-    "node_modules/webpack": {
-      "version": "5.89.0",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz",
-      "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==",
-      "dev": true,
-      "dependencies": {
-        "@types/eslint-scope": "^3.7.3",
-        "@types/estree": "^1.0.0",
-        "@webassemblyjs/ast": "^1.11.5",
-        "@webassemblyjs/wasm-edit": "^1.11.5",
-        "@webassemblyjs/wasm-parser": "^1.11.5",
-        "acorn": "^8.7.1",
-        "acorn-import-assertions": "^1.9.0",
-        "browserslist": "^4.14.5",
-        "chrome-trace-event": "^1.0.2",
-        "enhanced-resolve": "^5.15.0",
-        "es-module-lexer": "^1.2.1",
-        "eslint-scope": "5.1.1",
-        "events": "^3.2.0",
-        "glob-to-regexp": "^0.4.1",
-        "graceful-fs": "^4.2.9",
-        "json-parse-even-better-errors": "^2.3.1",
-        "loader-runner": "^4.2.0",
-        "mime-types": "^2.1.27",
-        "neo-async": "^2.6.2",
-        "schema-utils": "^3.2.0",
-        "tapable": "^2.1.1",
-        "terser-webpack-plugin": "^5.3.7",
-        "watchpack": "^2.4.0",
-        "webpack-sources": "^3.2.3"
-      },
-      "bin": {
-        "webpack": "bin/webpack.js"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependenciesMeta": {
-        "webpack-cli": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/webpack-bundle-analyzer": {
-      "version": "4.10.1",
-      "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz",
-      "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==",
-      "dev": true,
-      "dependencies": {
-        "@discoveryjs/json-ext": "0.5.7",
-        "acorn": "^8.0.4",
-        "acorn-walk": "^8.0.0",
-        "commander": "^7.2.0",
-        "debounce": "^1.2.1",
-        "escape-string-regexp": "^4.0.0",
-        "gzip-size": "^6.0.0",
-        "html-escaper": "^2.0.2",
-        "is-plain-object": "^5.0.0",
-        "opener": "^1.5.2",
-        "picocolors": "^1.0.0",
-        "sirv": "^2.0.3",
-        "ws": "^7.3.1"
-      },
-      "bin": {
-        "webpack-bundle-analyzer": "lib/bin/analyzer.js"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      }
-    },
-    "node_modules/webpack-bundle-analyzer/node_modules/commander": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
-      "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/webpack-chain": {
-      "version": "6.5.1",
-      "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz",
-      "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==",
-      "dev": true,
-      "dependencies": {
-        "deepmerge": "^1.5.2",
-        "javascript-stringify": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/webpack-dev-middleware": {
-      "version": "5.3.3",
-      "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
-      "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
-      "dev": true,
-      "dependencies": {
-        "colorette": "^2.0.10",
-        "memfs": "^3.4.3",
-        "mime-types": "^2.1.31",
-        "range-parser": "^1.2.1",
-        "schema-utils": "^4.0.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^4.0.0 || ^5.0.0"
-      }
-    },
-    "node_modules/webpack-dev-middleware/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
-      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3"
-      },
-      "peerDependencies": {
-        "ajv": "^8.8.2"
-      }
-    },
-    "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/webpack-dev-middleware/node_modules/schema-utils": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
-      "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.9",
-        "ajv": "^8.9.0",
-        "ajv-formats": "^2.1.1",
-        "ajv-keywords": "^5.1.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/webpack-dev-server": {
-      "version": "4.15.1",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz",
-      "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==",
-      "dev": true,
-      "dependencies": {
-        "@types/bonjour": "^3.5.9",
-        "@types/connect-history-api-fallback": "^1.3.5",
-        "@types/express": "^4.17.13",
-        "@types/serve-index": "^1.9.1",
-        "@types/serve-static": "^1.13.10",
-        "@types/sockjs": "^0.3.33",
-        "@types/ws": "^8.5.5",
-        "ansi-html-community": "^0.0.8",
-        "bonjour-service": "^1.0.11",
-        "chokidar": "^3.5.3",
-        "colorette": "^2.0.10",
-        "compression": "^1.7.4",
-        "connect-history-api-fallback": "^2.0.0",
-        "default-gateway": "^6.0.3",
-        "express": "^4.17.3",
-        "graceful-fs": "^4.2.6",
-        "html-entities": "^2.3.2",
-        "http-proxy-middleware": "^2.0.3",
-        "ipaddr.js": "^2.0.1",
-        "launch-editor": "^2.6.0",
-        "open": "^8.0.9",
-        "p-retry": "^4.5.0",
-        "rimraf": "^3.0.2",
-        "schema-utils": "^4.0.0",
-        "selfsigned": "^2.1.1",
-        "serve-index": "^1.9.1",
-        "sockjs": "^0.3.24",
-        "spdy": "^4.0.2",
-        "webpack-dev-middleware": "^5.3.1",
-        "ws": "^8.13.0"
-      },
-      "bin": {
-        "webpack-dev-server": "bin/webpack-dev-server.js"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      },
-      "peerDependencies": {
-        "webpack": "^4.37.0 || ^5.0.0"
-      },
-      "peerDependenciesMeta": {
-        "webpack": {
-          "optional": true
-        },
-        "webpack-cli": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/webpack-dev-server/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/webpack-dev-server/node_modules/ajv-keywords": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
-      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3"
-      },
-      "peerDependencies": {
-        "ajv": "^8.8.2"
-      }
-    },
-    "node_modules/webpack-dev-server/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/webpack-dev-server/node_modules/schema-utils": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
-      "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.9",
-        "ajv": "^8.9.0",
-        "ajv-formats": "^2.1.1",
-        "ajv-keywords": "^5.1.0"
-      },
-      "engines": {
-        "node": ">= 12.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/webpack-dev-server/node_modules/ws": {
-      "version": "8.14.2",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
-      "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": ">=5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/webpack-merge": {
-      "version": "5.10.0",
-      "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
-      "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
-      "dev": true,
-      "dependencies": {
-        "clone-deep": "^4.0.1",
-        "flat": "^5.0.2",
-        "wildcard": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/webpack-sources": {
-      "version": "3.2.3",
-      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
-      "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/webpack-virtual-modules": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz",
-      "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==",
-      "dev": true
-    },
-    "node_modules/webpack/node_modules/schema-utils": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
-      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
-      "dev": true,
-      "dependencies": {
-        "@types/json-schema": "^7.0.8",
-        "ajv": "^6.12.5",
-        "ajv-keywords": "^3.5.2"
-      },
-      "engines": {
-        "node": ">= 10.13.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
-      }
-    },
-    "node_modules/websocket-driver": {
-      "version": "0.7.4",
-      "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
-      "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
-      "dev": true,
-      "dependencies": {
-        "http-parser-js": ">=0.5.1",
-        "safe-buffer": ">=5.1.0",
-        "websocket-extensions": ">=0.1.1"
-      },
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/websocket-extensions": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
-      "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/whatwg-fetch": {
-      "version": "3.6.19",
-      "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz",
-      "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==",
-      "dev": true
-    },
-    "node_modules/whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
-      "dev": true,
-      "dependencies": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "node_modules/which": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
-      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "which": "bin/which"
-      }
-    },
-    "node_modules/wildcard": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
-      "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
-      "dev": true
-    },
-    "node_modules/wrap-ansi": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "dev": true
-    },
-    "node_modules/ws": {
-      "version": "7.5.9",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
-      "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8.3.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/y18n": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yallist": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-      "dev": true
-    },
-    "node_modules/yaml": {
-      "version": "1.10.2",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
-      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/yargs": {
-      "version": "16.2.0",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
-      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
-      "dev": true,
-      "dependencies": {
-        "cliui": "^7.0.2",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.0",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^20.2.2"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yargs-parser": {
-      "version": "20.2.9",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/zrender": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.2.tgz",
-      "integrity": "sha512-bIusJLS8c4DkIcdiK+s13HiQ/zjQQVgpNohtd8d94Y2DnJqgM1yjh/jpDb8DoL6hd7r8Awagw8e3qK/oLaWr3g=="
-    }
-  }
-}

+ 0 - 34
foodie_sj_vue/package.json

@@ -1,34 +0,0 @@
-{
-  "name": "eleliugang",
-  "version": "0.1.0",
-  "private": true,
-  "scripts": {
-    "serve": "vue-cli-service serve",
-    "dev": "vue-cli-service serve --mode development",
-    "serve:test": "vue-cli-service serve --mode test",
-    "build": "vue-cli-service build --mode production",
-    "build:dev": "vue-cli-service build --mode development",
-    "build:test": "vue-cli-service build --mode test"
-  },
-  "dependencies": {
-    "@googlemaps/js-api-loader": "^1.16.2",
-    "axios": "^1.3.6",
-    "core-js": "^3.8.3",
-    "echarts": "^4.9.0",
-    "element-ui": "^2.15.13",
-    "js-cookie": "^3.0.5",
-    "jsencrypt": "^3.3.2",
-    "v-charts": "^1.19.0",
-    "vue": "^2.6.14",
-    "vue-i18n": "^7.3.2",
-    "vue-json-excel": "^0.3.0",
-    "vue-router": "^3.5.1",
-    "file-saver": "2.0.5"
-  },
-  "devDependencies": {
-    "@vue/cli-plugin-babel": "~5.0.0",
-    "@vue/cli-plugin-router": "~5.0.0",
-    "@vue/cli-service": "~5.0.0",
-    "vue-template-compiler": "^2.6.14"
-  }
-}

BIN
foodie_sj_vue/public/favicon.ico


+ 0 - 17
foodie_sj_vue/public/index.html

@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html lang="">
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width,initial-scale=1.0">
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
-  </head>
-  <body>
-    <noscript>
-      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-    </noscript>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
-</html>

+ 0 - 10
foodie_sj_vue/src/App.vue

@@ -1,10 +0,0 @@
-<template>
-  <div id="app">
-    <router-view/>
-  </div>
-</template>
-<style>
-	#app{
-		height: 100%;
-	}
-</style>

+ 0 - 56
foodie_sj_vue/src/api/fenlei.js

@@ -1,56 +0,0 @@
-import request from '@/router/request';
-
-
-//添加商品分类
-export function addfenlei(data){
-  return request({
-    url: '/system/fenlei/addfenlei',
-    method: 'post',
-    headers: {
-      isToken: false,
-    },
-    data:data
-  })
-}
-//删除商品分类
-export function delefenle(id){
-  return request({
-    url: '/system/fenlei/delefenlei',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params: {
-      id:id,
-    }
-  })
-}
-//获取商品分类
-export function getordfenlei(id,lang){
-  return request({
-    url: '/system/fenlei/getfenlei',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      id:id,
-	  language:lang
-    }
-  })
-}
-
-// 获取商家门店列表
-export function storelistlist(){
-  return request({
-    url: '/chanting/store/storelistlist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:{
-		page:1,
-		size:50
-	}
-  })
-}

+ 0 - 90
foodie_sj_vue/src/api/food.js

@@ -1,90 +0,0 @@
-import request from '@/router/request';
-
-// 删除商品
-export function delefood(id){
-  return request({
-    url: '/chanting/food/delefood',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:{
-    	id:id
-    }
-  })
-}
-
-
-export function getFood(id) {
-  return request({
-    url: '/chanting/food/' + id,
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-  })
-}
-// 添加商品
-export function setposfood(data){
-  return request({
-    url: '/chanting/food/setposfood',
-    method: 'post',
-    headers: {
-      isToken: false,
-    },
-    data:data
-  })
-}
-// 获取商品列表
-export function getidlist(id,lang,name){
-  return request({
-    url: '/chanting/food/getidlist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:{
-		id:id,
-		language:lang,
-        name:name
-	}
-  })
-}
-// 获取商家门店列表
-export function storelistlist(){
-  return request({
-    url: '/chanting/store/storelistlist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:{
-		page:1,
-		size:50
-	}
-  })
-}
-//获取商品分类
-export function getordfenlei(id,lang){
-  return request({
-    url: '/system/fenlei/getfenlei',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      id:id,
-	  language:lang
-    }
-  })
-}
-export function getFoodPageList(params){
-  return request({
-    url: '/chanting/food/getFoodPageList',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:params
-  })
-}

+ 0 - 61
foodie_sj_vue/src/api/geocoding.js

@@ -1,61 +0,0 @@
-import request from '@/router/request';
-
-// 使用高德地图API进行地理编码
-export function getAddressByAmap(lat, lng) {
-  return request({
-    url: '/utils/amap/geocode',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      lat: lat,
-      lng: lng
-    }
-  })
-}
-
-// 使用百度地图API进行地理编码
-export function getAddressByBaidu(lat, lng) {
-  return request({
-    url: '/utils/baidu/geocode',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      lat: lat,
-      lng: lng
-    }
-  })
-}
-
-// 使用腾讯地图API进行地理编码
-export function getAddressByTencent(lat, lng) {
-  return request({
-    url: '/utils/tencent/geocode',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      lat: lat,
-      lng: lng
-    }
-  })
-}
-
-// 批量获取地址(多个服务商)
-export function getAddressBatch(lat, lng) {
-  return request({
-    url: '/utils/geocode/batch',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      lat: lat,
-      lng: lng
-    }
-  })
-}

+ 0 - 51
foodie_sj_vue/src/api/index.js

@@ -1,51 +0,0 @@
-import request from '@/router/request';
-
-//获取商户统计
-export function getindex(id){
-  return request({
-    url: '/index/getshindex',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      id:id
-    }
-  })
-}
-// 获取商家订单列表
-export function getshordlist(data){
-  return request({
-    url: '/index/getstoreorderlist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params: data
-  })
-}
-// 获取商家门店列表
-export function getstorelist(){
-  return request({
-    url: '/chanting/store/getmystorelist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    }
-  })
-}
-// //修改订单状态
-export function setorder(data){
-  return request({
-    url: '/system/order/setorderuzt',
-    method: 'post',
-    headers: {
-      isToken: true,
-    },
-	data:data
-  })
-}
-
-
-
-

+ 0 - 37
foodie_sj_vue/src/api/loding.js

@@ -1,37 +0,0 @@
-import request from '@/router/request';
-
-// 登录
-export function loding(data){
-  return request({
-    url: '/infouser/user/shanglodeing',
-    method: 'post',
-    headers: {
-      isToken: false,
-    },
-    data: data
-  })
-}
-//获取用户详情
-export function getuser(){
-  return request({
-    url: '/infouser/user/getuserinfo',
-    method: 'get',
-    headers: {
-      isToken: true,
-    }
-  })
-}
-//修改语言
-export function changeLanguages(lang){
-  return request({
-    url: '/changeLanguages',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      lang: lang,
-      id:"admin"
-    }
-  })
-}

+ 0 - 59
foodie_sj_vue/src/api/promotion.js

@@ -1,59 +0,0 @@
-import request from '@/router/request';
-
-// 查询SalesshSalesPromotion列表
-export function listshSalesPromotion(query) {
-    return request({
-        url: '/system/shSalesPromotion/list',
-        method: 'get',
-        params: query,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 查询SalesshSalesPromotion详细
-export function getshSalesPromotion(id) {
-    return request({
-        url: '/system/shSalesPromotion/' + id,
-        method: 'get',
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 新增SalesshSalesPromotion
-export function addshSalesPromotion(data) {
-    return request({
-        url: '/system/shSalesPromotion',
-        method: 'post',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 修改SalesshSalesPromotion
-export function updateshSalesPromotion(data) {
-    return request({
-        url: '/system/shSalesPromotion',
-        method: 'put',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 删除SalesshSalesPromotion
-export function delshSalesPromotion(id) {
-    return request({
-        url: '/system/shSalesPromotion/' + id,
-        method: 'delete',
-        headers: {
-            isToken: true,
-        },
-    })
-}

+ 0 - 59
foodie_sj_vue/src/api/quanyi.js

@@ -1,59 +0,0 @@
-import request from '@/router/request';
-
-// 查询quanyi列表
-export function listQuanyi(query) {
-    return request({
-        url: '/system/shQuanyi/list',
-        method: 'get',
-        params: query,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 查询quanyi详细
-export function getQuanyi(id) {
-    return request({
-        url: '/system/shQuanyi/' + id,
-        method: 'get',
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 新增quanyi
-export function addQuanyi(data) {
-    return request({
-        url: '/system/shQuanyi',
-        method: 'post',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 修改quanyi
-export function updateQuanyi(data) {
-    return request({
-        url: '/system/shQuanyi',
-        method: 'put',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 删除quanyi
-export function delQuanyi(id) {
-    return request({
-        url: '/system/shQuanyi/' + id,
-        method: 'delete',
-        headers: {
-            isToken: true,
-        },
-    })
-}

+ 0 - 59
foodie_sj_vue/src/api/review.js

@@ -1,59 +0,0 @@
-import request from '@/router/request';
-
-// 查询review列表
-export function listReview(query) {
-    return request({
-        url: '/system/shPosReview/list',
-        method: 'get',
-        params: query,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 查询review详细
-export function getReview(id) {
-    return request({
-        url: '/system/shPosReview/' + id,
-        method: 'get',
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 新增review
-export function addReview(data) {
-    return request({
-        url: '/system/shPosReview',
-        method: 'post',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 修改review
-export function updateReview(data) {
-    return request({
-        url: '/system/shPosReview',
-        method: 'put',
-        data: data,
-        headers: {
-            isToken: true,
-        },
-    })
-}
-
-// 删除review
-export function delReview(id) {
-    return request({
-        url: '/system/shPosReview/' + id,
-        method: 'delete',
-        headers: {
-            isToken: true,
-        },
-    })
-}

+ 0 - 102
foodie_sj_vue/src/api/store.js

@@ -1,102 +0,0 @@
-import request from '@/router/request';
-
-//删除门店
-export function delemendian(id){
-  return request({
-    url: '/chanting/store/delemendian',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:{
-		id:id
-	}
-  })
-}
-//添加或修改门店
-export function addmendian(data){
-  return request({
-    url: '/chanting/store/addmendian',
-    method: 'post',
-    headers: {
-      isToken: false,
-    },
-    data:data
-  })
-}
-//坐标逆向地址
-export function getAddr(params){
-  return request({
-    url: '/utils/getAddr',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params:params
-  })
-}
-//获取门店分类
-export function getfenlei(){
-  return request({
-    url: '/fenlei/type/list',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      pageNum:1,
-	  pageSize:50
-    }
-  })
-}
-
-export function getfenleilistByTag(tag){
-  return request({
-    url: '/fenlei/type/listByTag?tag='+tag,
-    method: 'get',
-    headers: {
-      isToken: false,
-    }
-  })
-}
-
-
-// 获取商家门店列表
-export function storelistlist(data){
-  return request({
-    url: '/chanting/store/storelistlist',
-    method: 'get',
-    headers: {
-      isToken: true,
-    },
-    params:data
-  })
-}
-
-//获取服务类型
-export function getfwleixing(){
-  return request({
-    url: '/system/ServiceType/fwlxlist',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-    params: {
-      pageNum:1,
-	  pageSize:50
-    }
-  })
-}
-
-//获取夜市列表
-export function getNightMarketlist(){
-  return request({
-    url: '/user/index/getNightMarketList',
-    method: 'get',
-    headers: {
-      isToken: false,
-    },
-  })
-}
-
-

BIN
foodie_sj_vue/src/assets/bag.jpg


BIN
foodie_sj_vue/src/assets/ddlan.png


BIN
foodie_sj_vue/src/assets/ktixian.png


BIN
foodie_sj_vue/src/assets/logo.png


BIN
foodie_sj_vue/src/assets/toux.png


BIN
foodie_sj_vue/src/assets/zshour.png


+ 0 - 33
foodie_sj_vue/src/components/Aside.vue

@@ -1,33 +0,0 @@
-<template>
-	<el-menu :default-openeds="['1']" style="height: 100%;" router>
-		<div style="width: 200px;line-height: 60px;text-align: center;">
-			<img src="../assets/logo.png" alt="" style="width: 40px;height: 40px;position: relative;top: 10px;right: 5px;">
-			<b>{{$t('route.cte')}}</b>
-		</div>
-<!-- 	  <el-submenu index="1">
-	    <template slot="title"><i class="el-icon-message"></i></template>
-	  </el-submenu> -->
-	  <el-menu-item index="/index"><i class="el-icon-stopwatch"></i>{{$t('route.home')}}</el-menu-item>
-    <el-menu-item index="/review"><i class="el-icon-stopwatch"></i>{{$t('route.ddpl')}}</el-menu-item>
-	  <el-submenu index="1">
-	    <template slot="title"><i class="el-icon-timer"></i>{{$t('route.mdguanli')}}</template>
-	    <el-menu-item index="/acidrollingcapacity"><i class="el-icon-paperclip"></i>{{$t('route.mdlist')}}</el-menu-item>
-	    <el-menu-item index="/acidrollingplan"><i class="el-icon-paperclip"></i>{{$t('route.mdfenlei')}}</el-menu-item>
-		<el-menu-item index="/acidrollingactual"><i class="el-icon-paperclip"></i>{{$t('route.spguanli')}}</el-menu-item>
-	  </el-submenu>
-    <el-submenu index="2">
-      <template slot="title"><i class="el-icon-timer"></i>{{$t('route.yuiquangl')}}</template>
-      <el-menu-item index="/quanyi"><i class="el-icon-paperclip"></i>{{$t('route.quanyi')}}</el-menu-item>
-      <el-menu-item index="/promotion"><i class="el-icon-paperclip"></i>{{$t('route.zxhd')}}</el-menu-item>
-    </el-submenu>
-	</el-menu>
-</template>
-
-<script>
-	export default{
-		name:"Aside"
-	}
-</script>
-
-<style>
-</style>

+ 0 - 48
foodie_sj_vue/src/components/Header.vue

@@ -1,48 +0,0 @@
-<template>
-	<div class="hengxl">
-		<div class="toubu">{{$t('route.biaoti')}}</div>
-		<div style="display: flex;align-items: center;">
-			<div style="display: flex;align-items: center;font-size: 13px;justify-content: space-between; margin-right: 20px;">
-				<div style="margin-right: 20px;">{{$t('loding.lang')}}</div>
-				<i18n-select></i18n-select>
-			</div>
-			<div @click="tuichudenglu">{{$t('route.degnlu')}}</div>
-		</div>
-	</div>
-</template>
-
-<script>
-	import i18nSelect from "./i18n.vue"
-	export default{
-		components: { i18nSelect },
-		name:"Header",
-		methods:{
-			tuichudenglu(){
-				this.$confirm(this.$t('route.qttuicu'), this.$t('route.tishi'), {
-				  confirmButtonText:this.$t('route.tued'),
-				  cancelButtonText: this.$t('route.quxiao'),
-				  type: 'warning'
-				}).then(() => {
-					localStorage.removeItem('token');
-					localStorage.removeItem('user');
-					this.$router.push('/');
-				}).catch(() => {
-       
-				});
-			}
-		}
-	}
-</script>
-
-<style>
-	.toubu{
-		font-size: 15px;
-		font-weight: 600;
-	}
-	.hengxl{
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		padding-left: 20px;
-	}
-</style>

+ 0 - 308
foodie_sj_vue/src/components/googlemap.vue

@@ -1,308 +0,0 @@
-<template>
-  <div class="content">
-    <div v-if="mapType == 'selectPoint'" style="display: flex;align-items: center;margin-bottom: 20px;">
-      <div>{{$t('mendian.SearchAddress')}}:</div>
-      <input
-          id="pac-input"
-          type="text"
-          :placeholder="$t('mendian.Pleasekeywords')"
-      />
-      <div style="margin-left: 20px;">{{$t('mendian.currentlocation')}}:{{address}}</div>
-    </div>
-    <div :style="googleMapStyle" class="googleMap" :id="mapID"></div>
-  </div>
-</template>
-
-<script>
-import {getfenlei,storelistlist,getAddr} from '@/api/store';
-import { Loader } from "@googlemaps/js-api-loader"
-
-export default {
-  name:'googlemap',
-  props: {
-    //mapType属性值为:
-    //selectPoint时是地图选点
-    //POLYGON是绘制地图多边形区域
-
-    //地图id
-    mapID: {
-      type: String,
-      default: () => {
-        return 'googleMap'
-      },
-    },
-    //谷歌地图类型
-    mapType: {
-      type: String,
-      default: () => {
-        return 'default'
-      },
-    },
-    //谷歌地图样式
-    googleMapStyle: {
-      type: Object,
-      default: () => {
-        return {
-          wdith: '100%',
-          height: '500px',
-        }
-      },
-    },
-    //谷歌地图配置
-    mapOptions: {
-      type: Object,
-      default: () => {
-        return {
-          //为了关闭默认控件集,设置地图的disableDefaultUI的属性为true
-          disableDefaultUI: false,
-          // 启用缩放和平移
-          gestureHandling: 'greedy',
-          panControl: true,
-          zoomControl: true,
-          scaleControl: true,
-          //关闭街景
-          streetViewControl: false,
-        }
-      },
-    },
-    //谷歌地图中心点
-    googleMapCenter: {
-      type: Object,
-      default: () => {
-        return {
-          lat: 21.031859020043132,
-          lng:105.82760815495604
-        }
-      },
-    },
-    //谷歌地图缩放级别
-    zoom: {
-      type: Number,
-      default() {
-        return 11
-      },
-    },
-    //谷歌地图图形path
-    mapPath: {
-      type: String,
-      default: () => {
-        return ''
-      },
-    },
-  },
-  data() {
-    return {
-      //地图选点回显值
-      longlat: 21.031859020043132 + ',' + 105.82760815495604,
-      //标记点
-      marker: [],
-      //图形实例
-      graphicalExample: null,
-      //图形路径经纬度
-      graphicalPath: [],
-      apiKey: 'AIzaSyBt-bYNprVqfpY3fPgoOj0RKbnC_g7ii1k', //旧的AIzaSyAnz_I0VUlPvt73NIocb_7tomJOW4CdwHk
-      map:null,
-      googMap:null,
-      googMarker:null,
-      address:''
-    }
-  },
-  created() {
-    this.initMap();
-  },
-  methods:{
-
-    // initMap is now async
-    async initMap() {
-      var that = this;
-      const loader = new Loader({
-        apiKey: this.apiKey,
-        version: "weekly",
-        libraries: ['places', 'drawing'], //插件库places为基础库 drawing为绘制工具库
-        language: this.$t('loding.language')
-      });
-      const mapOptions = {
-        center: { lat: this.googleMapCenter.lat * 1, lng: this.googleMapCenter.lng * 1 }, //中心点
-        zoom: this.zoom, //缩放级别
-        mapId:this.mapID,
-        ...this.mapOptions, //其他配置
-      }
-      await loader.load().then(async () => {
-        this.googMap = await google.maps.importLibrary("maps");
-        this.googMarker = await google.maps.importLibrary("marker");
-        this.map = new this.googMap.Map(document.getElementById(this.mapID), mapOptions);
-        this.map.addListener('click', (e) => {
-          console.log('点击事件',e);
-          this.marker.map = null;
-          this.marker = new this.googMarker.AdvancedMarkerElement({
-            map:this.map,
-            position: { lat: e.latLng.lat(), lng: e.latLng.lng() },
-          });
-        })
-      });
-    },
-    // 逆向地址
-    // getdizhi(lat){
-    // 	var user = JSON.parse(localStorage.getItem('user'));
-    // 	var params={
-    // 		latlng:lat,
-    // 		id:user.id
-    // 	}
-    // 	getAddr(params).then(res=>{
-    // 		this.address = res.data.address
-    // 		this.$emit('golat',{lat:lat,address:res.data.address})
-    // 	})
-    // },
-    // //回显图形
-    // echoGraphical() {
-    // 	if (this.mapType == 'POLYGON') {
-    // 		//回显多边形
-    // 		this.graphicalPath = this.mapPath
-    // 		let paths = JSON.parse(this.graphicalPath)
-    // 		// Construct a draggable red triangle with geodesic set to true.
-    // 		this.graphicalExample = new this.googleApi.maps.Polygon({
-    // 			paths,
-    // 			fillColor: 'blue',
-    // 			strokeColor: 'blue',
-    // 			strokeOpacity: 0.8,
-    // 			fillOpacity: 0.4,
-    // 			strokeWeight: 5,
-    // 			clickable: true,
-    // 			editable: true,
-    // 			zIndex: 1,
-    // 		})
-    // 		this.graphicalExample.setMap(this.googleMap)
-    // 		//监听回显图形每一个路径点
-    // 		this.googleApi.maps.event.addListener(this.graphicalExample.getPath(), 'insert_at', (event) => {
-    // 			this.setPath(this.graphicalExample.getPath().Ld)
-    // 		})
-    // 		this.googleApi.maps.event.addListener(this.graphicalExample.getPath(), 'set_at', (event) => {
-    // 			this.setPath(this.graphicalExample.getPath().Ld)
-    // 		})
-    // 	}
-    // },
-    // //path路径emit传出
-    // setPath(path) {
-    // 	this.graphicalPath = []
-    // 	if (path.length > 0) {
-    // 		path.forEach((v) => {
-    // 			this.graphicalPath.push({ lat: v.lat(), lng: v.lng() })
-    // 		})
-    // 		this.$emit('getGraphicalPath', this.graphicalPath)
-    // 	}
-    // },
-    // //搜索地点方法
-    // selectPoint() {
-    // 	const input = document.getElementById('pac-input')
-    // 	const searchBox = new this.googleApi.maps.places.SearchBox(input)
-    // 	const infoWindow = new this.googleApi.maps.InfoWindow()
-    // 	// this.googleMap.controls[this.googleApi.maps.ControlPosition.TOP_LEFT].push(input)
-    // 	this.googleMap.addListener('click', (e) => {
-    // 		this.clickGmap(e)
-    // 	})
-    // 	this.googleMap.addListener('bounds_changed', () => {
-    // 		searchBox.setBounds(this.googleMap.getBounds())
-    // 		let markers = []
-    // 		searchBox.addListener('places_changed', () => {
-    // 			const places = searchBox.getPlaces()
-
-    // 			if (places.length == 0) {
-    // 				return
-    // 			}
-
-    // 			// Clear out the old markers.
-    // 			markers.forEach((marker) => {
-    // 				marker.setMap(null)
-    // 			})
-    // 			markers = []
-
-    // 			// For each place, get the icon, name and location.
-    // 			const bounds = new this.googleApi.maps.LatLngBounds()
-
-    // 			places.forEach((place) => {
-    // 				if (!place.geometry || !place.geometry.location) {
-    // 					// console.log('Returned place contains no geometry')
-    // 					return
-    // 				}
-
-    // 				const icon = {
-    // 					url: place.icon,
-    // 					size: new this.googleApi.maps.Size(71, 71),
-    // 					origin: new this.googleApi.maps.Point(0, 0),
-    // 					anchor: new this.googleApi.maps.Point(17, 34),
-    // 					scaledSize: new this.googleApi.maps.Size(25, 25),
-    // 				}
-
-    // 				// Create a marker for each place.
-    // 				markers.push(
-    // 					new this.googleApi.maps.marker.AdvancedMarkerElement({
-    // 						map: this.googleMap,
-    // 						icon,
-    // 						title: place.name,
-    // 						position: place.geometry.location,
-    // 						draggable: false,
-    // 						title: 'Uluru'
-    // 					})
-    // 				)
-    // 				if (place.geometry.viewport) {
-    // 					// Only geocodes have viewport.
-    // 					bounds.union(place.geometry.viewport)
-    // 				} else {
-    // 					bounds.extend(place.geometry.location)
-    // 				}
-    // 			})
-    // 			this.googleMap.fitBounds(bounds)
-    // 		})
-    // 	})
-    // },
-    // //点击地图回调
-    // clickGmap(e) {
-    // 	console.log('点击回调',e)
-    // 	this.longlat = e.latLng.lat() + ',' + e.latLng.lng()
-    // 	this.$emit('setLongLat', this.longlat)
-    // 	this.addDraggableMarkers(1, true, { lat: e.latLng.lat(), lng: e.latLng.lng() })
-    // 	this.getdizhi(this.longlat);
-    // },
-    // //移动标记点回调
-    // updateMaker(e) {
-    // 	console.log('移动回调',e)
-    // 	this.longlat = e.latLng.lat() + ',' + e.latLng.lng()
-    // 	this.$emit('setLongLat', this.longlat)
-    // },
-    // //添加可拖动的标记点
-    // addDraggableMarkers(max, draggable, { lat = 0, lng = 0 }) {
-    // 	if (max != -1) {
-    // 		this.marker.forEach((marker) => {
-    // 			marker.setMap(null)
-    // 		})
-    // 		this.marker = []
-    // 	}
-    // 	this.marker.push(
-    // 		new this.googleApi.maps.Marker({
-    // 			map: this.googleMap,
-    // 			position: { lat: lat, lng: lng },
-    // 			draggable: draggable,
-    // 		})
-    // 	)
-    // 	if (draggable) {
-    // 		this.marker[0].addListener('dragend', (e) => {
-    // 			this.updateMaker(e)
-    // 		})
-    // 	}
-    // },
-    //获取经纬度
-    // getLongLat() {
-    // 	return this.longlat
-    // },
-    //设置地图中心点位置
-    // setMapPanBy(e) {
-    // 	let latlng = new this.googleApi.maps.LatLng(e.lat,e.lng)
-    // 	this.googleMap.setCenter(latlng)
-    // 	this.marker[0].setPosition(latlng);
-    // },
-  }
-}
-</script>
-
-<style>
-</style>

+ 0 - 199
foodie_sj_vue/src/components/googmap.vue

@@ -1,199 +0,0 @@
-<template>
-  <div class="content">
-    <div style="display: flex;align-items: center;margin-bottom: 20px;">
-      <div>{{$t('mendian.SearchAddress')}}:</div>
-      <input
-          type="text"
-          v-model="ssneir"
-          :placeholder="$t('mendian.Pleasekeywords')"
-          @keyup.enter="selectPoint"
-      />
-      <button style="margin-left: 10px;" @click="selectPoint">{{$t('mendian.SearchAddress')}}</button>
-      <div style="margin-left: 20px;">{{$t('mendian.currentlocation')}}:{{address}}</div>
-    </div>
-    <!-- 添加地址选择提示 -->
-    <div v-if="!address" style="background-color: #fef0f0; color: #f56c6c; padding: 10px; margin-bottom: 10px; border-radius: 4px; display: flex; align-items: center;">
-      <i class="el-icon-warning" style="margin-right: 8px;"></i>
-      {{$t('mendian.Selectmapobtainaddress')}}
-    </div>
-    <div :style="googleMapStyle" class="googleMap" :id="mapID"></div>
-  </div>
-</template>
-
-<script>
-import {getfenlei,storelistlist,getAddr} from '@/api/store';
-import { Loader } from '@googlemaps/js-api-loader' //引入
-export default {
-  name:'googmap',
-  props: {
-    //selectPoint时是地图选点
-    //POLYGON是绘制地图多边形区域
-
-    //地图id
-    mapID: {
-      type: String,
-      default: () => {
-        return 'googleMap'
-      },
-    },
-    //谷歌地图样式
-    googleMapStyle: {
-      type: Object,
-      default: () => {
-        return {
-          wdith: '100%',
-          height: '500px',
-        }
-      },
-    },
-    //谷歌地图配置
-    mapOptions: {
-      type: Object,
-      default: () => {
-        return {
-          //为了关闭默认控件集,设置地图的disableDefaultUI的属性为true
-          disableDefaultUI: false,
-          // 启用缩放和平移
-          gestureHandling: 'greedy',
-          panControl: true,
-          zoomControl: true,
-          scaleControl: true,
-          //关闭街景
-          streetViewControl: false,
-        }
-      },
-    },
-    //谷歌地图中心点
-    googleMapCenter: {
-      type: Object,
-      default: () => {
-        return {
-          lat: 25.037798,
-          lng: 121.565170
-        }
-      },
-    },
-    //谷歌地图缩放级别
-    zoom: {
-      type: Number,
-      default() {
-        return 11
-      },
-    },
-    //谷歌地图图形path
-    mapPath: {
-      type: String,
-      default: () => {
-        return ''
-      },
-    },
-  },
-  data() {
-    return {
-      //地图选点回显值
-      longlat: 25.037798 + ',' + 121.565170,
-      //标记点
-      marker: [],
-      //图形实例
-      graphicalExample: null,
-      //图形路径经纬度
-      graphicalPath: [],
-      apiKey: 'AIzaSyBt-bYNprVqfpY3fPgoOj0RKbnC_g7ii1k', //旧的AIzaSyAnz_I0VUlPvt73NIocb_7tomJOW4CdwHk
-      googleMap: null,
-      address: '',
-      ssneir: ''
-    }
-  },
-  created() {
-    this.$nextTick(() => {
-      const loader = new Loader({
-        apiKey: this.apiKey, //之前的key
-        version: 'weekly', //版本
-        libraries: ['places', 'drawing'], //插件库places为基础库 drawing为绘制工具库
-        region: 'Canada',
-        language: this.$t('loding.language'),
-      })
-      const mapOptions = {
-        center: {lat: this.googleMapCenter.lat * 1, lng: this.googleMapCenter.lng * 1}, //中心点
-        zoom: this.zoom, //缩放级别
-        mapId: this.mapID,
-        ...this.mapOptions, //其他配置
-      }
-      loader.load().then(async (google) => {
-        this.googMap = await google.maps.importLibrary("maps");
-        this.googMarker = await google.maps.importLibrary("marker");
-        const map = new this.googMap.Map(document.getElementById(this.mapID), mapOptions);
-        this.googleMap = map;
-        this.googleApi = google;
-        this.googleMap.addListener('click', (e) => {
-          this.clickGmap(e)
-        })
-      }).catch((e) => {
-        // do something
-        // console.log(e)
-      })
-    })
-  },
-  methods: {
-    // 逆向地址
-    getdizhi(lat) {
-      var user = JSON.parse(localStorage.getItem('user'));
-
-      var params = {
-        latlng: lat,
-        id: user.id
-      }
-      getAddr(params).then(res => {
-        console.log('地址', res)
-        this.address = res.data.address
-        this.$emit('golat', {lat: lat, address: res.data.address})
-      })
-    },
-    //搜索地点方法
-    selectPoint() {
-      if (!this.ssneir) return;
-      if (!this.googleApi || !this.googleMap) return;
-      const service = new this.googleApi.maps.places.PlacesService(this.googleMap);
-      service.textSearch({query: this.ssneir}, (results, status) => {
-        if (status === this.googleApi.maps.places.PlacesServiceStatus.OK && results.length > 0) {
-          const loc = results[0].geometry.location;
-          const lat = loc.lat();
-          const lng = loc.lng();
-          this.googleMap.setCenter({lat, lng});
-          this.googleMap.setZoom(15);
-          if (this.marker) this.marker.map = null;
-          this.marker = new this.googMarker.AdvancedMarkerElement({
-            map: this.googleMap,
-            position: {lat, lng},
-          });
-          this.getdizhi(lat + ',' + lng);
-        }
-      });
-    },
-    //点击地图回调
-    clickGmap(e) {
-      console.log('点击回调', e)
-      this.longlat = e.latLng.lat() + ',' + e.latLng.lng();
-      this.marker.map = null;
-      this.marker = new this.googMarker.AdvancedMarkerElement({
-        map: this.googleMap,
-        position: {lat: e.latLng.lat(), lng: e.latLng.lng()},
-      });
-      this.getdizhi(this.longlat);
-    },
-    //获取经纬度
-    // getLongLat() {
-    // 	return this.longlat
-    // },
-    //设置地图中心点位置
-    // setMapPanBy(e) {
-    // 	let latlng = new this.googleApi.maps.LatLng(e.lat,e.lng)
-    // 	this.googleMap.setCenter(latlng)
-    // 	this.marker[0].setPosition(latlng);
-    // },
-  }
-}
-</script>
-
-<style>
-</style>

+ 0 - 59
foodie_sj_vue/src/components/i18n.vue

@@ -1,59 +0,0 @@
-<template>
-  <div>
-    <el-select style="width: 250px"  @change="changeLanguage" v-model="lang">
-      <el-option v-for="lan in langList"
-                 :key="lan.value"
-                 :label="lan.label"
-                 :value="lan.value">
-      </el-option>
-    </el-select>
-  </div>
-</template>
-<script>
-import {isNotNull} from "@/lang/index";
-import { changeLanguages } from "@/api/loding";
-import Bus from '../utils/Bus.js'
-export default {
-  name: "i18n",
-  data(){
-    return {
-      lang: "tw",
-      langList: [
-			// {
-			// 	label: "Tiếng Việt",
-			// 	value: "vi"
-			// },
-        {
-          label: "繁體中文",
-          value: "tw"
-        },
-			// {
-			// 	label: "简体中文",
-			// 	value: "zh"
-			// },
-			// {
-			// 	label: "English",
-			// 	value: "en"
-			// }
-      ],
-    }
-  },
-  created() {
-    let value = localStorage.getItem("lang") || "tw";
-	// console.log('========================',value)
-	 this.lang = value;
-	 this.changeLanguage(value);
-  },
-  methods: {
-    changeLanguage(value){
-      this.$i18n.locale = value;
-      localStorage.setItem("lang", value);
-      changeLanguages(value).then(response => {
-        // console.info("change-language:" + value);
-        Bus.$emit('l18zh',value);
-        // window.location.reload();
-      });
-    },
-  }
-}
-</script>

+ 0 - 349
foodie_sj_vue/src/lang/en.js

@@ -1,349 +0,0 @@
-// en.js
-export default {
-	dongtai:{
-		Unaccepted:'Unaccepted',
-		Accepted:'Accepted',
-		Mealalreadyserved:'Meal already served',
-		RefundAftersales:'Refund/After sales'
-	},
-	loding:{
-		language:'en',
-		lass:'en',
-		cte:'CTE-COOPERATE',
-		lang:'language',
-		username:'username',
-		pasd:'password',
-		logng:'log on',
-		txuse:'Please fill in your username',
-		txpad:'Please fill in the password'
-	},
-	route: {
-		cte:'CTE',
-		home:'home',
-		mdguanli:'Store Management',
-		mdlist:'Store List',
-		mdfenlei:'CATEGORY',
-		spguanli:'product control',
-		biaoti: 'Welcome to CTE-COOPERATE',
-		degnlu: 'exit',
-		qttuicu: 'Are you sure you want to log out?',
-		tishi:'prompt',
-		tued:'determine',
-		quxiao:'cancellation',
-		yuiquangl: 'Coupon Management',
-		zxhd: 'Promotion Management',
-		quanyi: 'Available Coupons',
-		ddpl:'Order Review',
-    },
-	index:{
-		newdd:'Latest orders',
-		ddid:'Order No.',
-		cretim:'Order time',
-		amount:'Amount',
-		address:'Shipping address',
-		jvli:'Delivery distance',
-		ddodr:'commodity',
-		type:'type',
-		tangs:'Dine in',
-		ziqu:'ask for',
-		waisong:'takeaway',
-		collectPayment:'cash on delivery',
-		yes:'yes',
-		nos:'no',
-		right:'operate',
-		chak:'view',
-		jiedan:'accept',
-		chucan:'Dining out',
-		tishi:'prompt',
-		tisiyu:'Are you sure you want to process the order?',
-		quxiao:'cancellation',
-		qued:'determine',
-		xiangq:'details',
-		freight:'Delivery fee',
-		qishou:'Order taking rider',
-		foods:'commodity',
-		guanbi:'close',
-		shus:'Merchant',
-		sqsu:'rider',
-		user:'user',
-		dpshu:'Number of stores',
-		ddsour:'Daily income',
-		dddingd:'Same day order',
-		zongsr:'Total income',
-		zddlng:'Total order quantity',
-		ketixan:'Withdrawable amount',
-		beizu:'notes',
-		cxhdxx: "Promotion Information",
-		ptcxhd: "Platform Promotions",
-		sjcxhd: "Merchant Promotions",
-		jm: "Discount/Deduction",
-		yhqxx: "Coupon Information",
-		ptyhq: "Platform Coupons",
-		sjyhq: "Merchant Coupons",
-		yhje: "Discount Amount",
-		none:"None",
-		export: 'Export',
-		jfsyqk: 'Points Utilization',
-		jfsysl: 'Points Consumed',
-		jfdkje: 'Deducted Amount',
-		startTime: 'Start Time',
-		endTime: 'End Time'
-	},
-	mendian:{
-		home:'home',
-		Management:'Store Management',
-		StoreList:'Store List',
-		AddStore:'Add Store',
-		logo:'logo',
-		StoreCover:'Store Cover',
-		StoreName:'Store Name',
-		Startingprice:'Minimum delivery price',
-		openBusiness:'Open For Business',
-		windingUp:'winding-up',
-		area:'area',
-		Telephone:'Service phone number',
-		operate:'operate',
-		modify:'modify',
-		delete:'delete',
-		Enterstorename:'Please enter the store name',
-		address:'address',
-		InputAddress:'Please enter the store address',
-		coordinate:'coordinate',
-		Positioningobtaincoordinates:'Please click on the location icon to obtain the store coordinates',
-		Storetype:'Store type',
-		Restaurant:'Restaurant',
-		Supermarket:'Supermarket',
-		Fillintheprice:'Fill in the minimum delivery price',
-		Fillphonenumber:'Fill in customer service phone number',
-		FillopenBusiness:'Fill in the start time of business, for example: 8:00',
-		FillwindingUp:'Fill in the closing time, for example: 18:00',
-		classification:'classification',
-		Pleaseselect:'Please select',
-		ServiceType:'Service Type',
-		Fooddelivery:'Food delivery',
-		Dinein:'Dine in',
-		Selfpickuptakeout:'Self pickup of takeout',
-		Summericedrink:'Summer ice drink',
-		Exquisiteafternoontea:'Exquisite afternoon tea',
-		state:'state',
-		trade:'trade',
-		close:'close',
-		determine:'determine',
-		cancellation:'cancellation',
-		selectaddress:'select address',
-		Covercannotempty:'Store cover cannot be empty',
-		Namecannotempty:'Store name cannot be empty',
-		Addresscannotempty:'Store address cannot be empty',
-		Coordinatescannotempty:'Coordinates cannot be empty',
-		openBusinesscannotempty:'The opening hours cannot be empty',
-		windingUpcannotempty:'The closing time cannot be empty',
-		Classifiedmandatory:'Classified as mandatory',
-		Selectservicetype:'At least one service type must be selected',
-		prompt:'prompt',
-		youwanttodeleteit:'Are you sure you want to delete this store?',
-		successful:'Delete successful',
-		Deletefailed:'Failed, please try again',
-		undelete:'Cancelled deletion',
-		ModifyStore:'Modify Store',
-		Selectmapobtainaddress:'Please click on the map to obtain the address',
-		ItcanonlyJPG:'Uploading avatar images can only be in JPG format!',
-		Cannotexceed:'The size of the uploaded avatar image cannot exceed 2MB!',
-		SearchAddress:'Search Address',
-		Pleasekeywords:'Please enter keywords',
-		currentlocation:'current location',
-		openingtime: 'Business Hours',
-		addTime: 'Add Time Slot',
-		zssjd: 'Please add at least one operating time slot',
-		mgsjd: 'Each time slot must have both start and end time'
-	},
-	fenlei:{
-		home:'home',
-		Management:'Store Management',
-		CATEGORY:'CATEGORY',
-		Addcategory:'Add product category',
-		Classiname:'Classification name',
-		operate:'operate',
-		modify:'modify',
-		delete:'delete',
-		Plearname:'Please enter the category name',
-		determine:'determine',
-		cancellation:'cancellation',
-		Classifyempty:'Category name cannot be empty',
-		successfully:'Submitted successfully!',
-		Modifyclass:'Modify classification',
-		prompt:'prompt',
-		DeleteCategory:'Are you sure you want to delete this category?',
-		successful:'Delete successful',
-		Deletefailed:'Failed, please try again',
-		undelete:'Cancelled deletion',
-		id:'id',
-		sodi:'Please enter the sorting ID, the larger the number, the higher it will be'
-	},
-	foots:{
-		home:'home',
-		Management:'Store Management',
-		Commodityfood:'Commodity management',
-		classification:'classification',
-		addproduct:'add product',
-		Tradename:'Trade name',
-		Commoditypicture:'Commodity picture',
-		commodityprice:'commodity price',
-		illustrate:'illustrate',
-		operate:'operate',
-		modify:'modify',
-		delete:'delete',
-		Enterproductname:'Please enter the product name',
-		Enterproductprice:'Please enter the product price',
-		Attributes:'Attributes',
-		AddType:'Add Type',
-		Radio:'Radio',
-		multiplechoice:'multiple choice',
-		optional:'optional',
-		required:'required',
-		Introduction:'Product Introduction',
-		EnterIntroduction:'Please enter the product description',
-		Dorecommendit:'Do you recommend it',
-		Productsorting:'Product sorting',
-		Anynumber:'Fill in any numerical value, with values ranked first',
-		determine:'determine',
-		cancellation:'cancellation',
-		typename:'type-name',
-		InputMerchantType:'Please enter the product type',
-		Multiplechoices:'Do you want to select multiple options',
-		Isitmandatory:'Is it mandatory',
-		Addspecifications:'Add specifications',
-		formname:'form name',
-		Entercationname:'Please enter the specification name',
-		Specificationprice:'Specification price',
-		Enterandprices:'Please enter the specification price',
-		description:'description',
-		Entercationiption:'Please enter the specification description',
-		Imagebeempty:'The image cannot be empty',
-		Namebeempty:'Name cannot be empty',
-		Pricebeempty:'Price cannot be empty',
-		Thenamebeempty:'The specification name cannot be empty',
-		Typenamebeempty:'Type name cannot be empty',
-		prompt:'prompt',
-		Confirmdeletion:'Are you sure you want to delete the product type?',
-		Unabletodelete:'This type has specifications and cannot be deleted',
-		DeleteSpecification:'Are you sure you want to delete the product specifications?',
-		Modifyproduct:'Modify product',
-		Deletethisproduct:'Are you sure you want to delete this product?',
-		successful:'Delete successful',
-		Deletefailed:'Failed, please try again',
-		undelete:'Cancelled deletion',
-		ItcanonlyJPG:'Uploading avatar images can only be in JPG format!',
-		Cannotexceed:'The size of the uploaded avatar image cannot exceed 2MB!',
-		search: 'Search',
-		reset: 'Reset'
-	},
-	cuxiao: {
-		home: 'Home',
-		yuiquangl: 'Coupon Management',
-		zxhd: 'Promotion Management',
-		AddCX: 'Add New',
-		hdmc: 'Promotion Name',
-		hdmcms: 'Please enter promotion name',
-		hdhb: 'Promotion Poster',
-		qmfs: 'Discount Type',
-		qmyf: 'Shipping Fee',
-		ddjdz: 'Order',
-		ddjdk: 'Product',
-		qmz: 'Discount Value',
-		qmzsm: 'Leave blank for free shipping. For 30% discount enter 0.3. For 1000 deduction enter 1000',
-		sytj: 'Usage Condition',
-		sytjsm: 'Leave blank for no condition. Enter 1000 for minimum order amount of 1000',
-		salesFund: 'Usage Limit',
-		salesFundsm: 'Leave blank for unlimited use. Enter 1 for one-time use per user',
-		endTime: 'End Date',
-		endTimesm: 'Please select promotion end date',
-		salesState: 'Promotion Status',
-		salesStateKq: 'Active',
-		salesStateTy: 'Inactive',
-		illustrate: 'Description',
-		illustratesm: 'Please enter description',
-		jsrq: 'End Date',
-		hdzt: 'Promotion Status',
-		operate: 'Action',
-		modify: 'Edit',
-		delete: 'Delete',
-		hdmcEpty: 'Promotion name cannot be empty',
-		qmfsEmty: 'Discount type is required',
-		endTimeEmty: "End date is required",
-		salesStateEmty: "Promotion status is required",
-		salesReductionEmty: "Discount value is required",
-		salesReduction0: "Order/Product discount value must be greater than 0",
-		delSm: 'Are you sure you want to delete this record?',
-		ItcanonlyJPG: 'Only JPG format images can be uploaded!',
-		Cannotexceed: 'Image size cannot exceed 2MB!',
-		bnxg:'This promotion has been used by customers; only the status can be modified, while other core fields remain unchangeable',
-	},
-	quanyi: {
-		kyyhq: 'Available Coupons',
-		add: 'Add New',
-		yhmc: 'Coupon Name',
-		yhfs: 'Discount Type',
-		sm: 'Description',
-		sytj: 'Usage Condition',
-		zt: 'Status',
-		qy: 'Enable',
-		gb: 'Disable',
-		yhqlx1: 'Shipping Fee',
-		yhqlx2: 'Order',
-		yhqlx3: 'Product',
-		yhqlx4: 'Specific Item Discount',
-		total: 'Total Coupons',
-		creatTime: 'Creation Date',
-		sryhmc: 'Please enter coupon name',
-		yhnum: 'Discount Value',
-		sryhnum: 'Enter 0 for free shipping, 0.7 for 30% discount , or 1000 for 1000 unit deduction',
-		yhmnum0: 'Order/Product discount value must be greater than 0',
-		srtotal: 'Please enter total number of coupons',
-		lqxz: 'Claim Limit Per User',
-		srlqxz: 'Please enter claim limit per user',
-		validity: "Validity Period (Days)",
-		srvalidity: 'Please enter validity period',
-		shuoming: 'Description',
-		srshuoming: 'Please enter description',
-		tiaojian: 'Usage Condition',
-		srtiaojian: 'Enter usage condition. 0 means no minimum. >0 means minimum spend amount',
-		nameEpty: 'Coupon name cannot be empty',
-		yhfangsEmpty: 'Please select discount type',
-		yhnumEmty: 'Discount value cannot be empty',
-		totalEmty: 'Total coupons cannot be empty',
-		lqxzEmty: 'Claim limit per user cannot be empty',
-		validityEmty: 'Validity period cannot be empty',
-		stateEmty: 'Please select status',
-		xcsp: 'Select Products',
-		qxcsp: 'Please select products',
-		md: "Store:",
-		xcmd: "Select Store",
-		spfl: 'Product Category:',
-		spmc: 'Product Name:',
-		cx: 'Search',
-		tp: 'Image',
-		jg: 'Price',
-		qx: 'Cancel',
-		qd: 'Confirm',
-		ItcanonlyJPG: 'Only JPG format images can be uploaded!',
-		Cannotexceed: 'Image size cannot exceed 2MB!',
-		bnxg:'This coupon has been redeemed. Only status can be modified; core fields are locked.',
-		claimedCount:'Claimed Quantity',
-	},
-	review:{
-		ddid:'Order ID',
-		srddid:'Enter order ID',
-		plsj:'Review time',
-		cz:'Action',
-		sc:'Delete',
-		ck:'View',
-		yhid:'User ID',
-		pf:'Rating',
-		plnr:'Review content',
-		sfnm:'Anonymous',
-		yes:'Yes',
-		no:'No',
-		pltp:'Review images',
-		ddpl:'Order review',
-	}
-}

+ 0 - 66
foodie_sj_vue/src/lang/index.js

@@ -1,66 +0,0 @@
-// 在 index.js 文件进行配置
-// 导入所需的库和资源: 代码中导入了 Vue.js 框架、Vue I18n 扩展以及各种语言版本的翻译资源,包括 Element UI 组件库的翻译。
-import Vue from 'vue'
-import VueI18n from 'vue-i18n'
-import Cookies from 'js-cookie'
-import elementViLocale from 'element-ui/lib/locale/lang/vi'// element-ui lang
-import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
-import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
-import elementTwLocale from 'element-ui/lib/locale/lang/zh-TW'// element-ui lang
-import viLocale from './vi'
-import enLocale from './en'
-import zhLocale from './zh'
-import twLocale from './tw'
-
-
-// 启用 Vue I18n:使其可以在 Vue 应用中使用。
-Vue.use(VueI18n)
-
-// 定义翻译信息: 创建一个名为 messages 的对象,其中包含不同语言的翻译信息。每个语言都由一个键值对表示,包括自定义的应用文本翻译和 Element UI 组件库的翻译信息。
-const messages = {
-	// vi: {
-	// 	...viLocale,
-	// 	...elementViLocale
-	// },
-	tw: {
-		...twLocale,
-		...elementTwLocale
-	},
-	en: {
-		...enLocale,
-		...elementEnLocale
-	},
-	zh: {
-		...zhLocale,
-		...elementZhLocale
-	}
-
-}
-// 确定用户语言偏好: 定义名为 getLanguage 的函数,根据用户选择的语言和浏览器语言设置来确定应该使用的语言。如果用户未选择语言或浏览器语言无匹配项,则默认使用英语。
-export function getLanguage() {
-  const chooseLanguage = Cookies.get('language')
-  if (chooseLanguage) return chooseLanguage
-
-  // if has not choose language
-  const language = (navigator.language || navigator.browserLanguage).toLowerCase()
-  const locales = Object.keys(messages)
-  for (const locale of locales) {
-    if (language.indexOf(locale) > -1) {
-      return locale
-    }
-  }
-  return 'vi'
-}
-
-// 创建 Vue I18n 实例: 使用 VueI18n 的构造函数创建一个名为 i18n 的实例。在构造函数中,通过传递当前语言代码和翻译信息来初始化实例。
-const i18n = new VueI18n({
-  // set locale
-  // options: en | zh | es
-  locale: getLanguage(),
-  // set locale messages
-  messages
-})
-
-// 导出 I18n 实例
-export default i18n
-

+ 0 - 349
foodie_sj_vue/src/lang/tw.js

@@ -1,349 +0,0 @@
-// zh.js
-export default {
-	dongtai:{
-		Unaccepted:'未受理',
-		Accepted:'已受理',
-		Mealalreadyserved:'已出餐',
-		RefundAftersales:'退款/售後'
-	},
-	loding:{
-		language:'zh-TW',
-		lass:'tw',
-		cte:'恰恰吃商戶管理',
-		lang:'選擇語言',
-		username:'用戶名',
-		pasd:'密碼',
-		logng:'登入',
-		txuse:'請填寫用戶名',
-		txpad:'請填寫密碼'
-	},
-	route: {
-		cte:'恰恰吃',
-		home:'首頁',
-		mdguanli:'門店管理',
-		mdlist:'門店清單',
-		mdfenlei:'商品分類',
-		spguanli:'商品管理',
-		biaoti: '歡迎使用恰恰吃商戶平臺',
-		degnlu: '登出',
-		qttuicu: '確定要登出嗎?',
-		tishi:'提示',
-		tued:'確定',
-		quxiao:'取消',
-		yuiquangl:'優惠券管理',
-		zxhd:'促銷活動管理',
-		quanyi: '可用優惠券',
-		ddpl:'訂單評論',
-    },
-	index:{
-		newdd:'最新訂單',
-		ddid:'訂單號',
-		cretim:'下單時間',
-		amount:'訂單金額',
-		address:'配送地址',
-		jvli:'配送距離',
-		ddodr:'訂單商品',
-		type:'訂單類型',
-		tangs:'堂食',
-		ziqu:'自取',
-		waisong:'外送',
-		collectPayment:'到付訂單',
-		yes:'是',
-		nos:'否',
-		right:'操作',
-		chak:'查看',
-		jiedan:'接單',
-		chucan:'出餐',
-		tishi:'提示',
-		tisiyu:'你確定要操作訂單嗎?',
-		quxiao:'取消',
-		qued:'確定',
-		xiangq:'詳情',
-		freight:'配送費',
-		qishou:'接單騎手',
-		foods:'訂單商品',
-		guanbi:'關閉',
-		shus:'商戶',
-		sqsu:'騎手',
-		user:'用戶',
-		dpshu:'店鋪數',
-		ddsour:'當日收入',
-		dddingd:'當日訂單',
-		zongsr:'總收入',
-		zddlng:'總訂單量',
-		ketixan:'可提現金額',
-		beizu:'備註',
-		cxhdxx:"促銷活動資訊",
-		ptcxhd:"平臺促銷活動",
-		sjcxhd:"商家促銷活動",
-		jm:"減免",
-		yhqxx:"優惠券資訊",
-		ptyhq:"平臺優惠券",
-		sjyhq:"商家優惠券",
-		yhje:"優惠金額",
-		none:"無",
-		export: '匯出',
-		jfsyqk: '積分使用情況',
-		jfsysl: '使用積分數量',
-		jfdkje: '折抵金額',
-		startTime: '開始時間',
-		endTime: '結束時間'
-	},
-	mendian:{
-		home:'首頁',
-		Management:'門店管理',
-		StoreList:'门店列表',
-		AddStore:'添加门店',
-		logo:'logo',
-		StoreCover:'门店封面',
-		StoreName:'门店名称',
-		Startingprice:'起送价',
-		openBusiness:'開始營業',
-		windingUp:'結束營業',
-		area:'所在地區',
-		Telephone:'客服電話',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Enterstorename:'请输入店名称',
-		address:'地址',
-		InputAddress:'请输入店地址',
-		coordinate:'坐标',
-		Positioningobtaincoordinates:'请点击定位图标获取门店坐标',
-		Storetype:'门店类型',
-		Restaurant:'餐饮',
-		Supermarket:'商超',
-		Fillintheprice:'填写起送价格',
-		Fillphonenumber:'填写客服电话',
-		FillopenBusiness:'填寫開始營業時間,例:8:00',
-		FillwindingUp:'填寫結束營業時間,例:18:00',
-		classification:'分类',
-		Pleaseselect:'请选择',
-		ServiceType:'服务类型',
-		Fooddelivery:'美食外送',
-		Dinein:'堂食',
-		Selfpickuptakeout:'外卖自取',
-		Summericedrink:'夏日冰饮',
-		Exquisiteafternoontea:'精致下午茶',
-		state:'状态',
-		trade:'营业',
-		close:'打烊',
-		determine:'确定',
-		cancellation:'取消',
-		selectaddress:'选择地址',
-		Covercannotempty:'门店封面不能为空',
-		Namecannotempty:'门店名称不能为空',
-		Addresscannotempty:'门店地址不能为空',
-		Coordinatescannotempty:'坐标不能为空',
-		openBusinesscannotempty:'開始營業時間不能為空',
-		windingUpcannotempty:'結束營業時間不能為空',
-		Classifiedmandatory:'分类为必选项',
-		Selectservicetype:'至少要选择一个服务类型',
-		prompt:'提示',
-		youwanttodeleteit:'你确定要删除此门店吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		ModifyStore:'修改门店',
-		Selectmapobtainaddress:'请点选地图获取地址',
-		ItcanonlyJPG:'上传头像图片只能是 JPG 格式!',
-		Cannotexceed:'上传头像图片大小不能超过 2MB!',
-		SearchAddress:'搜索地址',
-		Pleasekeywords:'请输入关键字',
-		currentlocation:'当前位置',
-		openingtime:'营业时间',
-		addTime:'新增时间段',
-		zssjd:'请至少添加一个营业时间段',
-		mgsjd:'每个时间段都需填写开始和结束时间'
-	},
-	fenlei:{
-		home:'首页',
-		Management:'门店管理',
-		CATEGORY:'商品分类',
-		Addcategory:'添加商品分类',
-		Classiname:'分类名称',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Plearname:'请输分类名称',
-		determine:'确定',
-		cancellation:'取消',
-		Classifyempty:'分类名不能为空',
-		successfully:'提交成功!',
-		Modifyclass:'修改分类',
-		prompt:'提示',
-		DeleteCategory:'你确定要删除此分类吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		id:'id',
-		sodi:'請輸入排序id,數位越大越靠前'
-	},
-	foots:{
-		home:'首页',
-		Management:'门店管理',
-		Commodityfood:'商品管理',
-		classification:'分类',
-		addproduct:'添加商品',
-		Tradename:'商品名称',
-		Commoditypicture:'商品图片',
-		commodityprice:'商品价格',
-		illustrate:'说明',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Enterproductname:'请输入商品名称',
-		Enterproductprice:'请输入商品价格',
-		Attributes:'商品属性',
-		AddType:'添加类型',
-		Radio:'单选',
-		multiplechoice:'多选',
-		optional:'可选',
-		required:'必选',
-		Introduction:'商品介绍',
-		EnterIntroduction:'请输入商品介绍',
-		Dorecommendit:'是否推荐',
-		Productsorting:'商品排序',
-		Anynumber:'填任何数值,值大排在前',
-		determine:'确定',
-		cancellation:'取消',
-		typename:'类型名称',
-		InputMerchantType:'请输入商品类型',
-		Multiplechoices:'是否多选',
-		Isitmandatory:'是否必选',
-		Addspecifications:'添加规格',
-		formname:'规格名称',
-		Entercationname:'请输入规格名称',
-		Specificationprice:'规格价格',
-		Enterandprices:'请输入规格价格',
-		description:'规格说明',
-		Entercationiption:'请输入规格说明',
-		Imagebeempty:'图片不能为空',
-		Namebeempty:'名称不能为空',
-		Pricebeempty:'价格不能为空',
-		Thenamebeempty:'规格名不能为空',
-		Typenamebeempty:'类型名不能为空',
-		prompt:'提示',
-		Confirmdeletion:'你确定要删除商品类型吗?',
-		Unabletodelete:'此类型存在规格,无法删除',
-		DeleteSpecification:'你确定要删除商品规格吗?',
-		Modifyproduct:'修改商品',
-		Deletethisproduct:'你确定要删除此商品吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		ItcanonlyJPG:'上传头像图片只能是 JPG 格式!',
-		Cannotexceed:'上传头像图片大小不能超过 2MB!',
-		search: '查詢',
-		reset: '重設'
-	},
-	cuxiao: {
-		home: '首頁',
-		yuiquangl: '優惠券管理',
-		zxhd: '促銷活動管理',
-		AddCX: '新增',
-		hdmc: '活動名稱',
-		hdmcms: '請輸入促銷活動名稱',
-		hdhb: '活動海報',
-		qmfs: '減免方式',
-		qmyf: '運費',
-		ddjdz: '訂單',
-		ddjdk: '商品',
-		qmz: '減免值',
-		qmzsm: '選免運費可留空,如選打折如7折請填0.7,如選抵扣1000請填1000',
-		sytj: '使用條件',
-		sytjsm: '留空為無任何使用條件,如填1000為訂單金額滿1000可用',
-		salesFund: '可用次數',
-		salesFundsm: '留空為無限使用,如填1為此活動每個用戶只能使用一次',
-		endTime: '結束日期',
-		endTimesm: '請選擇活動結束日期',
-		salesState: '活動狀態',
-		salesStateKq: '開啟',
-		salesStateTy: '停用',
-		illustrate: '活動說明',
-		illustratesm: '請輸入內容',
-		jsrq: '結束日期',
-		hdzt: '活動狀態',
-		operate: '操作',
-		modify: '修改',
-		delete: '刪除',
-		hdmcEpty: '活動名稱不能空白',
-		qmfsEmty: '減免方式為必選',
-		endTimeEmty: "結束日期為必選",
-		salesStateEmty: "活動狀態為必選",
-		salesReductionEmty:'減免值為必填欄位',
-		salesReduction0:'選擇訂單/商品優惠時,減免值必須大於0',
-		delSm: '是否確認刪除此紀錄?',
-		ItcanonlyJPG: '上傳圖片只能是 JPG 格式!',
-		Cannotexceed: '上傳圖片大小不能超過 2MB!',
-		bnxg:'此促銷活動已有用戶參與,僅可修改狀態,無法變更其他核心參數',
-	},
-	quanyi: {
-		kyyhq: '可用優惠券',
-		add: '新增',
-		yhmc: '優惠券名稱',
-		yhfs: '優惠方式',
-		sm: '說明',
-		sytj: '使用條件',
-		zt: '狀態',
-		qy: '啟用',
-		gb: '關閉',
-		yhqlx1: '運費',
-		yhqlx2: '訂單',
-		yhqlx3: '商品',
-		yhqlx4: '減免個別商品',
-		total: '優惠券總數',
-		creatTime: '建立時間',
-		sryhmc: '請輸入優惠券名稱',
-		yhnum: '優惠值',
-		sryhnum:'免運費請填0,如選擇折扣(例如7折請填0.7),如選擇折抵1000請填1000',
-		yhmnum0:'選擇訂單、商品值必須大於0',
-		srtotal: '請輸入優惠券總數',
-		lqxz: '每人可領取數量',
-		srlqxz: '請輸入每人可領取的數量',
-		validity: "有效期限(天)",
-		srvalidity: '請輸入有效期',
-		shuoming: '說明',
-		srshuoming: '請輸入說明',
-		tiaojian: '使用條件',
-		srtiaojian: '請輸入使用條件,0為無門檻,大於0為消費滿額可用',
-		nameEpty: '優惠券名稱不能空白',
-		yhfangsEmpty: '請選擇優惠方式',
-		yhnumEmty: '優惠值不能空白',
-		totalEmty: '優惠券總數不能空白',
-		lqxzEmty: '每人可領取數量不能空白',
-		validityEmty: '有效天數不能空白',
-		stateEmty: '請選擇狀態',
-		xcsp: '選擇商品',
-		qxcsp: '請選擇商品',
-		md: "門市:",
-		xcmd: "選擇門市",
-		spfl: '商品分類:',
-		spmc: '商品名稱:',
-		cx: '查詢',
-		tp: '圖片',
-		jg: '價格',
-		qx: '取消',
-		qd: '確定',
-		ItcanonlyJPG: '上傳圖片只能是 JPG 格式!',
-		Cannotexceed: '上傳圖片大小不能超過 2MB!',
-		bnxg:'本優惠券已有用戶領取,僅能修改狀態,無法變更其他核心欄位',
-		claimedCount:'已領取數量',
-	},
-	review:{
-		ddid:'訂單id',
-		srddid:'請輸入訂單id',
-		plsj:'評論時間',
-		cz:'操作',
-		sc:'刪除',
-		ck:'查看',
-		yhid:'用戶id',
-		pf:'評分',
-		plnr:'評論內容',
-		sfnm:'是否匿名',
-		yes:'是',
-		no:'否',
-		pltp:'評論圖片',
-		ddpl:'訂單評論',
-	}
-}

+ 0 - 349
foodie_sj_vue/src/lang/vi.js

@@ -1,349 +0,0 @@
-// vi.js
-export default {
-	dongtai:{
-		Unaccepted:'Chưa xử lý',
-		Accepted:'Đã xử lý',
-		Mealalreadyserved:'Đã ra món',
-		RefundAftersales:'Hoàn tiền/Hậu mãi'
-	},
-	loding:{
-		language:'vi',
-		lass:'vi',
-		cte:'Hệ thống quản lý nhà hàng CTE cooperace',
-		lang:'Lựa chọn ngôn ngữ',
-		username:'Tên người dùng',
-		pasd:'mật khẩu',
-		logng:'Đăng nhập',
-		txuse:'Hãy điền tên người dùng',
-		txpad:'Hãy điền mật khẩu'
-	},
-	route: {
-		cte:'CTE',
-		home:'Trang chủ',
-		mdguanli:'Quản lý cửa hàng',
-		mdlist:'Danh sách cửa hàng',
-		mdfenlei:'Phân loại sản phẩm',
-		spguanli:'Quản lý sản phẩm',
-		biaoti: 'Chào mừng sử dụng nền tảng quản lý CTE cooperace',
-		degnlu: 'Đăng xuất',
-		qttuicu: 'Xác định muốn đăng xuất?',
-		tishi:'Gợi ý',
-		tued:'Xác định',
-		quxiao:'Huỷ bỏ',
-		yuiquangl: 'Quản lý voucher',
-		zxhd: 'Quản lý chương trình khuyến mãi',
-		quanyi: 'Voucher có thể sử dụng',
-		ddpl:'Đánh giá đơn hàng',
-	},
-	index:{
-		newdd:'Đơn hàng mới nhất',
-		ddid:'Số đơn hàng',
-		cretim:'Thời gian đặt hàng',
-		amount:'Số tiền đặt hàng',
-		address:'Địa chỉ giao hàng',
-		jvli:'Khoảng cách giao hàng',
-		ddodr:'Sản phẩm đơn hàng',
-		type:'Loại đơn đặt hàng',
-		tangs:'Dùng tại chỗ',
-		ziqu:'Tự đến lấy',
-		waisong:'Giao hàng',
-		collectPayment:'Đơn nhận hàng trả tiền',
-		yes:'Đúng',
-		nos:'Không',
-		right:'Thao tác',
-		chak:'Xem',
-		jiedan:'Nhận đơn',
-		chucan:'Ra món',
-		tishi:'Gợi ý',
-		tisiyu:'Bạn chắc chắn muốn thao tác đơn hàng chứ?',
-		quxiao:'Huỷ bỏ',
-		qued:'Xác nhận',
-		xiangq:'Thông tin',
-		freight:'Phí giao hàng',
-		qishou:'Tài xế nhận đơn',
-		foods:'Sản phẩm đơn hàng',
-		guanbi:'Đóng',
-		shus:'Thương gia',
-		sqsu:'Tài xế',
-		user:'Người Dùng',
-		dpshu:'Số lượng tiệm',
-		ddsour:'Thu nhập hôm nay',
-		dddingd:'Đơn đặt hàng hôm nay',
-		zongsr:'Tổng thu vào',
-		zddlng:'Tổng lượng đơn đặt hàng',
-		ketixan:'Tiền có thể rút tối đa',
-		beizu:'Ghi chú',
-		cxhdxx: "Thông tin khuyến mãi",
-		ptcxhd: "Chương trình khuyến mãi nền tảng",
-		sjcxhd: "Chương trình khuyến mãi của cửa hàng",
-		jm: "Giảm trừ",
-		yhqxx: "Thông tin voucher",
-		ptyhq: "Voucher nền tảng",
-		sjyhq: "Voucher cửa hàng",
-		yhje: "Số tiền ưu đãi",
-		none:"Không",
-		export: 'Xuất',
-		jfsyqk: 'Tình hình sử dụng điểm',
-		jfsysl: 'Số điểm đã sử dụng',
-		jfdkje: 'Số tiền được khấu trừ',
-		startTime: 'Thời gian bắt đầu',
-		endTime: 'Thời gian kết thúc'
-	},
-	mendian:{
-		home:'Trang chủ',
-		Management:'Quản lý cửa hàng',
-		StoreList:'Danh sách cửa hàng',
-		AddStore:'Thêm cửa hàng',
-		logo:'Logo cửa hàng',
-		StoreCover:'Hình ảnh cửa hàng',
-		StoreName:'Tên cửa hàng',
-		Startingprice:'Giao hàng từ',
-		openBusiness:'Bắt đầu kinh doanh',
-		windingUp:'Kết thúc kinh doanh',
-		area:'Quận',
-		Telephone:'Điện thoại',
-		operate:'Thao tác',
-		modify:'sửa',
-		delete:'Xoá',
-		Enterstorename:'Vui lòng nhập tên cửa hàng',
-		address:'Địa chỉ',
-		InputAddress:'Vui lòng nhập địa chỉ cửa hàng',
-		coordinate:'Vị trí',
-		Positioningobtaincoordinates:'Hãy nhấp chuột vào biểu tượng định vị để lấy vị trí',
-		Storetype:'Phân Loại dịch vụ cửa hàng',
-		Restaurant:'Nhà hàng',
-		Supermarket:'Siêu thị',
-		Fillintheprice:'Hãy điền giá tối thiểu giao',
-		Fillphonenumber:'Hãy điền điện thoại cửa hàng',
-		FillopenBusiness:'Điền giờ mở cửa, ví dụ: 8:00',
-		FillwindingUp:'Điền giờ đóng cửa, ví dụ: 18:00',
-		classification:'Phân loại',
-		Pleaseselect:'Hãy lựa chọn',
-		ServiceType:'Loại hình phục vụ',
-		Fooddelivery:'Giao hàng tận nơi',
-		Dinein:'Dùng tại chỗ',
-		Selfpickuptakeout:'Tự đến lấy',
-		Summericedrink:'Thức uống ngày hè',
-		Exquisiteafternoontea:'Tinh tế trà chiều',
-		state:'Trạng thái',
-		trade:'Kinh doanh',
-		close:'Đóng cửa',
-		determine:'Xác nhận',
-		cancellation:'Huỷ bỏ',
-		selectaddress:'Chọn địa chỉ',
-		Covercannotempty:'Ảnh bìa cửa hàng không được để trống',
-		Namecannotempty:'Tên cửa hàng không được để trống',
-		Addresscannotempty:'Địa chỉ cửa hàng không được để trống',
-		Coordinatescannotempty:'Vị trí không được để trống',
-		openBusinesscannotempty:'Thời gian mở cửa không được để trống',
-		windingUpcannotempty:'Thời gian đóng cửa không được để trống',
-		Classifiedmandatory:'Phân loại bắt buộc phải chọn',
-		Selectservicetype:'Ít nhất phải chọn một loại hình phục vụ',
-		prompt:'Gợi ý',
-		youwanttodeleteit:'Bạn chắc chắn muốn xoá bỏ cửa hàng đẫ chọn không?',
-		successful:'Xoá thành công',
-		Deletefailed:'Thất bại, xin thử lại',
-		undelete:'Đã huỷ bỏ xoá',
-		ModifyStore:'Chỉnh sửa cửa hàng',
-		Selectmapobtainaddress:'Hãy nhấp bản đồ để lấy địa chỉ',
-		ItcanonlyJPG:'Hình ảnh biểu tượng tải lên chỉ đuôi JPG!',
-		Cannotexceed:'Hình ảnh biểu tượng tải lên dung lượng không quá 2MB!',
-		SearchAddress:'Tìm kiếm địa chỉ',
-		Pleasekeywords:'Hãy nhập vào từ khoá',
-		currentlocation:'Vị trí hiện tại',
-		openingtime: 'Giờ mở cửa',
-		addTime: 'Thêm khung giờ',
-		zssjd: 'Vui lòng thêm ít nhất một khung giờ kinh doanh',
-		mgsjd: 'Mỗi khung giờ đều cần điền thời gian bắt đầu và kết thúc'
-	},
-	fenlei:{
-		home:'Trang chủ',
-		Management:'Quản lý cửa hàng',
-		CATEGORY:'Phân loại sản phẩm',
-		Addcategory:'Thêm phân loại sản phẩm',
-		Classiname:'Tên phân loại',
-		operate:'Thao tác',
-		modify:'Chỉnh sửa',
-		delete:'Xoá',
-		Plearname:'Hãy nhập tên phân loại',
-		determine:'Xác nhận',
-		cancellation:'Huỷ bỏ',
-		Classifyempty:'Tên phân loại không được bỏ trống',
-		successfully:'Lưu thành công!',
-		Modifyclass:'Chỉnh sửa phân loại',
-		prompt:'Gợi ý',
-		DeleteCategory:'Bạn chắc chắn muốn xoá bỏ phân loại này không?',
-		successful:'Xoá thành công',
-		Deletefailed:'Thất bại, mời thử lại',
-		undelete:'Đã huỷ bỏ xoá',
-		id:'id',
-		sodi:'Hãy nhập vào id thứ tự, số thứ tự càng lớn càng hiển thị trước'
-	},
-	foots:{
-		home:'Trang chủ',
-		Management:'Quản lý cửa hàng',
-		Commodityfood:'Quản lý sản phẩm',
-		classification:'Phân loại',
-		addproduct:'Thêm sản phẩm',
-		Tradename:'Tên sản phẩm',
-		Commoditypicture:'Hình ảnh sản phẩm',
-		commodityprice:'Giá sản phẩm',
-		illustrate:'Mô tả',
-		operate:'Thao tác',
-		modify:'Chỉnh sửa',
-		delete:'Xoá',
-		Enterproductname:'Vui lòng nhập tên sản phẩm',
-		Enterproductprice:'Vui lòng nhập giá sản phẩm',
-		Attributes:'Thuộc tính sản phẩm',
-		AddType:'Thêm danh mục tùy chọn',
-		Radio:'Chọn một',
-		multiplechoice:'Chọn nhiều',
-		optional:'Không bắt buộc chọn',
-		required:'Bắt buộc chọn',
-		Introduction:'Giới thiệu sản phẩm',
-		EnterIntroduction:'Xin nhập vào giới thiệu sản phẩm',
-		Dorecommendit:'Có đề xuất không',
-		Productsorting:'Thứ tự sản phẩm',
-		Anynumber:'Điền số thứ tự bất kỳ, số lớn hiển thị trước',
-		determine:'Xác định',
-		cancellation:'Huỷ bỏ',
-		typename:'Tên danh mục món tuỳ chọn',
-		InputMerchantType:'Xin nhập vào tên danh mục món tuỳ chọn',
-		Multiplechoices:'có phải được chọn nhiều',
-		Isitmandatory:'Có phải bắt buộc chọn',
-		Addspecifications:'Thêm món tuỳ chọn',
-		formname:'tên món tuỳ chọn',
-		Entercationname:'Xin nhập tên món tuỳ chọn',
-		Specificationprice:'Giá món tuỳ chọn',
-		Enterandprices:'Xin nhập giá món tuỳ chọn',
-		description:'Mô tả món tuỳ chọn',
-		Entercationiption:'Xin nhập vào nội dung mô tả món tuỳ chọn',
-		Imagebeempty:'Hình ảnh không được để trống',
-		Namebeempty:'Tên gọi không được để trống',
-		Pricebeempty:'Giá cả không được để trống',
-		Thenamebeempty:'Món tuỳ chọn không được để trống',
-		Typenamebeempty:'Tên danh mục món tuỳ chọn không được để trống',
-		prompt:'Gợi ý',
-		Confirmdeletion:'Bạn có chắc muốn xoá danh mục món tuỳ chọn không?',
-		Unabletodelete:'Danh mục món tuỳ chọn này tồn tại món tuỳ chọn, không thể xoá',
-		DeleteSpecification:'Bạn có chắc muốn xoá món tuỳ chọn này?',
-		Modifyproduct:'Chỉnh sửa sản phẩm',
-		Deletethisproduct:'Bạn có chắc muốn xoá sản phẩm này?',
-		successful:'Xoá thành công',
-		Deletefailed:'Thất bại, hãy thử lại',
-		undelete:'Đã huỷ bỏ xoá',
-		ItcanonlyJPG:'Hình ảnh biểu tượng tải lên định chỉ chỉ có thể là JPG!',
-		Cannotexceed:'Hình ảnh biểu tượng tải lên không thể vượt quá 2MB!',
-		search: 'Tìm kiếm',
-		reset: 'Đặt lại'
-	},
-	cuxiao: {
-		home: 'Trang chủ',
-		yuiquangl: 'Quản lý voucher',
-		zxhd: 'Quản lý chương trình khuyến mãi',
-		AddCX: 'Thêm mới',
-		hdmc: 'Tên chương trình',
-		hdmcms: 'Nhập tên chương trình khuyến mãi',
-		hdhb: 'Poster chương trình',
-		qmfs: 'Hình thức giảm giá',
-		qmyf: 'Phí vận chuyển',
-		ddjdz: 'Đơn hàng',
-		ddjdk: 'Sản phẩm',
-		qmz: 'Giá trị giảm',
-		qmzsm: 'Chọn miễn ship để trống. Giảm 30% nhập 0.7. Khấu trừ 1000 nhập 1000',
-		sytj: 'Điều kiện sử dụng',
-		sytjsm: 'Để trống nếu không có điều kiện. Nhập 1000 cho đơn tối thiểu 1000',
-		salesFund: 'Số lần sử dụng',
-		salesFundsm: 'Để trống nếu không giới hạn. Nhập 1 nếu mỗi user chỉ dùng 1 lần',
-		endTime: 'Ngày kết thúc',
-		endTimesm: 'Chọn ngày kết thúc chương trình',
-		salesState: 'Trạng thái',
-		salesStateKq: 'Kích hoạt',
-		salesStateTy: 'Tạm dừng',
-		illustrate: 'Mô tả',
-		illustratesm: 'Nhập nội dung mô tả',
-		jsrq: 'Ngày kết thúc',
-		hdzt: 'Trạng thái CTKM',
-		operate: 'Thao tác',
-		modify: 'Sửa',
-		delete: 'Xóa',
-		hdmcEpty: 'Tên chương trình không được trống',
-		qmfsEmty: 'Chọn hình thức giảm giá',
-		endTimeEmty: "Chọn ngày kết thúc",
-		salesStateEmty: "Chọn trạng thái",
-		salesReductionEmty: "Giá trị giảm trừ là bắt buộc",
-		salesReduction0: "Giá trị đơn hàng/sản phẩm phải lớn hơn 0 khi chọn hình thức giảm giá",
-		delSm: 'Xác nhận xóa bản ghi này?',
-		ItcanonlyJPG: 'Chỉ chấp nhận ảnh định dạng JPG!',
-		Cannotexceed: 'Kích thước ảnh không quá 2MB!',
-		bnxg:'Chương trình khuyến mãi đã có người dùng tham gia, chỉ được phép thay đổi trạng thái, không thể chỉnh sửa các thông số cốt lõi khác.',
-	},
-	quanyi: {
-		kyyhq: 'Voucher khả dụng',
-		add: 'Thêm mới',
-		yhmc: 'Tên voucher',
-		yhfs: 'Loại ưu đãi',
-		sm: 'Mô tả',
-		sytj: 'Điều kiện',
-		zt: 'Trạng thái',
-		qy: 'Bật',
-		gb: 'Tắt',
-		yhqlx1: 'Phí vận chuyển',
-		yhqlx2: 'Đơn hàng',
-		yhqlx3: 'Sản phẩm',
-		yhqlx4: 'Giảm giá sản phẩm',
-		total: 'Tổng voucher',
-		creatTime: 'Ngày tạo',
-		sryhmc: 'Nhập tên voucher',
-		yhnum: 'Giá trị ưu đãi',
-		sryhnum: 'Miễn phí vận chuyển điền 0, nếu chọn giảm giá (ví dụ 7% điền 0.7), nếu chọn khấu trừ 1000 điền 1000',
-		yhmnum0: 'Giá trị đơn hàng/sản phẩm phải lớn hơn 0',
-		srtotal: 'Nhập tổng số voucher',
-		lqxz: 'Giới hạn nhận/user',
-		srlqxz: 'Nhập giới hạn nhận mỗi user',
-		validity: "Thời hạn (ngày)",
-		srvalidity: 'Nhập thời hạn hiệu lực',
-		shuoming: 'Mô tả',
-		srshuoming: 'Nhập mô tả',
-		tiaojian: 'Điều kiện',
-		srtiaojian: 'Nhập điều kiện. 0 là không giới hạn. >0 là giá trị đơn tối thiểu',
-		nameEpty: 'Tên voucher không được trống',
-		yhfangsEmpty: 'Chọn loại ưu đãi',
-		yhnumEmty: 'Giá trị ưu đãi không được trống',
-		totalEmty: 'Tổng voucher không được trống',
-		lqxzEmty: 'Giới hạn nhận không được trống',
-		validityEmty: 'Thời hạn không được trống',
-		stateEmty: 'Chọn trạng thái',
-		xcsp: 'Chọn sản phẩm',
-		qxcsp: 'Vui lòng chọn sản phẩm',
-		md: "Cửa hàng:",
-		xcmd: "Chọn cửa hàng",
-		spfl: 'Danh mục:',
-		spmc: 'Tên sản phẩm:',
-		cx: 'Tìm kiếm',
-		tp: 'Hình ảnh',
-		jg: 'Giá',
-		qx: 'Hủy',
-		qd: 'Xác nhận',
-		ItcanonlyJPG: 'Chỉ chấp nhận ảnh định dạng JPG!',
-		Cannotexceed: 'Kích thước ảnh không quá 2MB!',
-		bnxg:'Phiếu ưu đãi đã có người dùng nhận, chỉ được phép thay đổi trạng thái, không thể sửa các thông số cốt lõi khác',
-		claimedCount:'Số lượng đã nhận',
-	},
-	review:{
-		ddid:'ID đơn hàng',
-		srddid:'Vui lòng nhập ID đơn hàng',
-		plsj:'Thời gian đánh giá',
-		cz:'Thao tác',
-		sc:'Xóa',
-		ck:'Xem',
-		yhid:'ID người dùng',
-		pf:'Điểm đánh giá',
-		plnr:'Nội dung đánh giá',
-		sfnm:'Ẩn danh',
-		yes:'Có',
-		no:'Không',
-		pltp:'Hình ảnh đánh giá',
-		ddpl:'Đánh giá đơn hàng',
-	}
-}

+ 0 - 350
foodie_sj_vue/src/lang/zh.js

@@ -1,350 +0,0 @@
-// zh.js
-export default {
-	dongtai:{
-		Unaccepted:'未受理',
-		Accepted:'已受理',
-		Mealalreadyserved:'已出餐',
-		RefundAftersales:'退款/售后'
-	},
-	loding:{
-		language:'zh-CN',
-		lass:'zh',
-		cte:'美食达商户管理',
-		lang:'选择语言',
-		username:'用户名',
-		pasd:'密码',
-		logng:'登录',
-		txuse:'请填写用户名',
-		txpad:'请填写密码'
-	},
-	route: {
-		cte:'美食达',
-		home:'首页',
-		mdguanli:'门店管理',
-		mdlist:'门店列表',
-		mdfenlei:'商品分类',
-		spguanli:'商品管理',
-		biaoti: '欢迎使用美食达商户平台',
-		degnlu: '退出登录',
-		qttuicu: '确定要退出登录吗?',
-		tishi:'提示',
-		tued:'确定',
-		quxiao:'取消',
-		yuiquangl:'优惠券管理',
-		zxhd:'促销活动管理',
-		quanyi:'可用优惠券',
-		ddpl:'订单评论',
-
-    },
-	index:{
-		newdd:'最新订单',
-		ddid:'订单号',
-		cretim:'下单时间',
-		amount:'订单金额',
-		address:'配送地址',
-		jvli:'配送距离',
-		ddodr:'订单商品',
-		type:'订单类型',
-		tangs:'堂食',
-		ziqu:'自取',
-		waisong:'外送',
-		collectPayment:'到付订单',
-		yes:'是',
-		nos:'否',
-		right:'操作',
-		chak:'查看',
-		jiedan:'接单',
-		chucan:'出餐',
-		tishi:'提示',
-		tisiyu:'你确定要操作订单吗?',
-		quxiao:'取消',
-		qued:'确定',
-		xiangq:'详情',
-		freight:'配送费',
-		qishou:'接单骑手',
-		foods:'订单商品',
-		guanbi:'关闭',
-		shus:'商户',
-		sqsu:'骑手',
-		user:'用户',
-		dpshu:'店铺数',
-		ddsour:'当日收入',
-		dddingd:'当日订单',
-		zongsr:'总收入',
-		zddlng:'总订单量',
-		ketixan:'可提现金额',
-		beizu:'备注',
-		cxhdxx:"促销活动信息",
-		ptcxhd:"平台促销活动",
-		sjcxhd:"商家促销活动",
-		jm:"减免",
-		yhqxx:"优惠券信息",
-		ptyhq:"平台优惠券",
-		sjyhq:"商家优惠券",
-		yhje:"优惠金额",
-		none:"无",
-		export:'导出',
-		jfsyqk:'积分使用情况',
-		jfsysl:'使用积分数量',
-		jfdkje:'抵扣金额',
-		startTime:'开始时间',
-		endTime:'结束时间',
-	},
-	mendian:{
-		home:'首页',
-		Management:'门店管理',
-		StoreList:'门店列表',
-		AddStore:'添加门店',
-		logo:'商标',
-		StoreCover:'门店封面',
-		StoreName:'门店名称',
-		Startingprice:'起送价',
-		openBusiness:'开始营业',
-		windingUp:'结束营业',
-		area:'所在地区',
-		Telephone:'客服电话',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Enterstorename:'请输入店名称',
-		address:'地址',
-		InputAddress:'请输入店地址',
-		coordinate:'坐标',
-		Positioningobtaincoordinates:'请点击定位图标获取门店坐标',
-		Storetype:'门店类型',
-		Restaurant:'餐饮',
-		Supermarket:'商超',
-		Fillintheprice:'填写起送价格',
-		Fillphonenumber:'填写客服电话',
-		FillopenBusiness:'填写开始营业时间,例:8:00',
-		FillwindingUp:'填写结束营业时间,例:18:00',
-		classification:'分类',
-		Pleaseselect:'请选择',
-		ServiceType:'服务类型',
-		Fooddelivery:'美食外送',
-		Dinein:'堂食',
-		Selfpickuptakeout:'外卖自取',
-		Summericedrink:'夏日冰饮',
-		Exquisiteafternoontea:'精致下午茶',
-		state:'状态',
-		trade:'营业',
-		close:'打烊',
-		determine:'确定',
-		cancellation:'取消',
-		selectaddress:'选择地址',
-		Covercannotempty:'门店封面不能为空',
-		Namecannotempty:'门店名称不能为空',
-		Addresscannotempty:'门店地址不能为空',
-		Coordinatescannotempty:'坐标不能为空',
-		openBusinesscannotempty:'开始营业时间不能为空',
-		windingUpcannotempty:'结束营业时间不能为空',
-		Classifiedmandatory:'分类为必选项',
-		Selectservicetype:'至少要选择一个服务类型',
-		prompt:'提示',
-		youwanttodeleteit:'你确定要删除此门店吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		ModifyStore:'修改门店',
-		Selectmapobtainaddress:'请点选地图获取地址',
-		ItcanonlyJPG:'上传头像图片只能是 JPG 格式!',
-		Cannotexceed:'上传头像图片大小不能超过 2MB!',
-		SearchAddress:'搜索地址',
-		Pleasekeywords:'请输入关键字',
-		currentlocation:'当前位置',
-		openingtime:'营业时间',
-		addTime:'新增时间段',
-		zssjd:'请至少添加一个营业时间段',
-		mgsjd:'每个时间段都需填写开始和结束时间'
-	},
-	fenlei:{
-		home:'首页',
-		Management:'门店管理',
-		CATEGORY:'商品分类',
-		Addcategory:'添加商品分类',
-		Classiname:'分类名称',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Plearname:'请输分类名称',
-		determine:'确定',
-		cancellation:'取消',
-		Classifyempty:'分类名不能为空',
-		successfully:'提交成功!',
-		Modifyclass:'修改分类',
-		prompt:'提示',
-		DeleteCategory:'你确定要删除此分类吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		id:'id',
-		sodi:'请输入排序id,数字越大越靠前'
-	},
-	foots:{
-		home:'首页',
-		Management:'门店管理',
-		Commodityfood:'商品管理',
-		classification:'分类',
-		addproduct:'添加商品',
-		Tradename:'商品名称',
-		Commoditypicture:'商品图片',
-		commodityprice:'商品价格',
-		illustrate:'说明',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		Enterproductname:'请输入商品名称',
-		Enterproductprice:'请输入商品价格',
-		Attributes:'商品属性',
-		AddType:'添加类型',
-		Radio:'单选',
-		multiplechoice:'多选',
-		optional:'可选',
-		required:'必选',
-		Introduction:'商品介绍',
-		EnterIntroduction:'请输入商品介绍',
-		Dorecommendit:'是否推荐',
-		Productsorting:'商品排序',
-		Anynumber:'填任何数值,值大排在前',
-		determine:'确定',
-		cancellation:'取消',
-		typename:'类型名称',
-		InputMerchantType:'请输入商品类型',
-		Multiplechoices:'是否多选',
-		Isitmandatory:'是否必选',
-		Addspecifications:'添加规格',
-		formname:'规格名称',
-		Entercationname:'请输入规格名称',
-		Specificationprice:'规格价格',
-		Enterandprices:'请输入规格价格',
-		description:'规格说明',
-		Entercationiption:'请输入规格说明',
-		Imagebeempty:'图片不能为空',
-		Namebeempty:'名称不能为空',
-		Pricebeempty:'价格不能为空',
-		Thenamebeempty:'规格名不能为空',
-		Typenamebeempty:'类型名不能为空',
-		prompt:'提示',
-		Confirmdeletion:'你确定要删除商品类型吗?',
-		Unabletodelete:'此类型存在规格,无法删除',
-		DeleteSpecification:'你确定要删除商品规格吗?',
-		Modifyproduct:'修改商品',
-		Deletethisproduct:'你确定要删除此商品吗?',
-		successful:'删除成功',
-		Deletefailed:'失败,请重试',
-		undelete:'已取消删除',
-		ItcanonlyJPG:'上传头像图片只能是 JPG 格式!',
-		Cannotexceed:'上传头像图片大小不能超过 2MB!',
-		search:'查询',
-		reset:'重置'
-	},
-	cuxiao:{
-		home:'首页',
-		yuiquangl:'优惠券管理',
-		zxhd:'促销活动管理',
-		AddCX:'新增',
-		hdmc:'活动名称',
-		hdmcms:'请输入促销活动名称',
-		hdhb:'活动海报',
-		qmfs:'减免方式',
-		qmyf:'运费',
-		ddjdz:'订单',
-		ddjdk:'商品',
-		qmz:'减免值',
-		qmzsm:'免运费填0,如选打折如7折请填0.7,如选抵扣1000请填1000',
-		sytj:'使用条件',
-		sytjsm:'如空为无任何使用条件,如填1000为订单金额满1000可用',
-		salesFund:'可用次数',
-		salesFundsm:'如空值为无限使用,如填1为此活动每个用户只能使用一次',
-		endTime:'结束日期',
-		endTimesm:'请选择活动结束日期',
-		salesState:'活动状态',
-		salesStateKq:'开启',
-		salesStateTy:'停用',
-		illustrate:'活动说明',
-		illustratesm:'请输入内容',
-		jsrq:'结束日期',
-		hdzt:'活动状态',
-		operate:'操作',
-		modify:'修改',
-		delete:'删除',
-		hdmcEpty:'活动名不能空',
-		qmfsEmty:'减免方式为必选',
-		endTimeEmty:"结束日期为必选",
-		salesStateEmty:"活动状态为必选",
-		salesReductionEmty:'减免值为必填',
-		salesReduction0:'减免方式选择订单、商品值必须大于0',
-		delSm:'是否确认删除该记录吗?',
-		ItcanonlyJPG:'上传图片只能是 JPG 格式!',
-		Cannotexceed:'上传图片大小不能超过 2MB!',
-		bnxg:'该促销活动已有用户使用,只能修改状态,不能修改其他核心字段',
-	},
-	quanyi:{
-		kyyhq:'可用优惠券',
-		add:'新增',
-		yhmc:'优惠券名称',
-		yhfs:'优惠方式',
-		sm:'说明',
-		sytj:'使用条件',
-		zt:'状态',
-		qy:'启用',
-		gb:'关闭',
-		yhqlx1:'运费',
-		yhqlx2:'订单',
-		yhqlx3:'商品',
-		yhqlx4:'减免个别商品',
-		total:'优惠券总数',
-		creatTime:'创建时间',
-		sryhmc:'请输入优惠券名称',
-		yhnum:'优惠值',
-		sryhnum:'免运费填写0,如选打折如7折请填0.7,如选抵扣1000请填1000',
-		yhmnum0:'选择订单、商品输入值必须大于0',
-		srtotal:'请输入优惠券总数',
-		lqxz:'每人能领取数量',
-		srlqxz:'请输入每人能领取的数量',
-		validity:"有效期限(天)",
-		srvalidity:'请输入有效期',
-		shuoming:'说明',
-		srshuoming:'请输入说明',
-		tiaojian:'使用条件',
-		srtiaojian:'请输入使用条件,0为无门槛,大于0为消费满金额可用',
-		nameEpty:'优惠券名称不能为空',
-		yhfangsEmpty:'请选择优惠方式',
-		yhnumEmty:'优惠值不能为空',
-		totalEmty:'优惠券总数不能为空',
-		lqxzEmty:'每人能领取的数量不能为空',
-		validityEmty:'有效天数不能为空',
-		stateEmty:'请选择状态',
-		xcsp:'选择商品',
-		qxcsp:'请选择商品',
-		md:"门店:",
-		xcmd:"选择门店",
-		spfl:'商品分类:',
-		spmc:'商品名称:',
-		cx:'查询',
-		tp:'图片',
-		jg:'价格',
-		qx:'取消',
-		qd:'确定',
-		ItcanonlyJPG:'上传图片只能是 JPG 格式!',
-		Cannotexceed:'上传图片大小不能超过 2MB!',
-		bnxg:'已有用户领取了该优惠券,只能修改状态,无法修改其他核心字段',
-		claimedCount:'已领取数量',
-	},
-	review:{
-		ddid:'订单id',
-		srddid:'请输入订单id',
-		plsj:'评论时间',
-		cz:'操作',
-		sc:'删除',
-		ck:'查看',
-		yhid:'用户id',
-		pf:'评分',
-		plnr:'评论内容',
-		sfnm:'是否匿名',
-		yes:'是',
-		no:'否',
-		pltp:'评论图片',
-		ddpl:'订单评论',
-	}
-}

+ 0 - 26
foodie_sj_vue/src/main.js

@@ -1,26 +0,0 @@
-import Vue from 'vue'
-import App from './App.vue'
-import router from './router'
-import ElementUI from 'element-ui';
-import VCharts from 'v-charts';
-import JsonExcel from 'vue-json-excel'
-import 'element-ui/lib/theme-chalk/index.css';
-import './router/gloable.css'
-import request from './router/request';
-import i18n from './lang' // internationalization
-
-Vue.config.productionTip = false
-Vue.use(ElementUI,{
-	size:"small",
-	i18n: (key, value) => i18n.t(key, value)
-	});
-Vue.use(VCharts);
-// Vue.use(VueI18n);
-Vue.prototype.request = request;
-Vue.component('downloadExcel', JsonExcel);
-new Vue({
-	el: '#app',
-	router,
-	i18n,
-	render: h => h(App)
-}).$mount('#app')

+ 0 - 190
foodie_sj_vue/src/router/gloable.css

@@ -1,190 +0,0 @@
-*{
-	margin: 0;
-	padding: 0;
-	box-sizing: border-box;
-}
-html,body{
-	height: 100%;
-}
-.waiwei{
-	padding: 10px;
-	background-color: #f8f8f8;
-	margin-top: 15px;
-}
-.dahengx{
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	margin-bottom: 15px;
-}
-.mtou{
-	margin-top: 15px;
-}
-.zuojge{
-	margin-left: 50px;
-	font-size: 14px;
-	font-weight: bold;
-	
-}
-.xisskuan{
-	display: flex;
-	align-items: center;
-	margin-bottom: 15px;
-}
-.duanlan{
-	width: 17%;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-}
-.shijxzlan{
-	width:430px;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	/* background-color: #ffaaff; */
-}
-.changriqi{
-	width:470px;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	/* background-color: #ffaaff; */
-}
-.xxshengc{
-	width: 37%;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-}
-.shijlan{
-	width: 400px;
-}
-.xiaozhi{
-	text-align: right;
-	width: 80px;
-	font-size: 10px;
-	margin-right: 5px;
-}
-.dakuandu{
-	width: 55%;
-	display: flex;
-	align-items: center;
-}
-.danquyu{
-	background-color: #F5F7FA;
-	width: 49.5%;
-}
-.xxbaoti{
-	padding: 10px 10px 5px 30px;
-	border-bottom: solid 0.1px #e5e5e5;
-	display: flex;
-	align-items: center;
-}
-.neirkuan{
-	width: 100%;
-	height: 500px;
-	padding: 10px 20px;
-}
-.duanneir{
-	width: 100%;
-	height: 400px;
-	padding: 30px 20px 0 20px;
-}
-.caxannu{
-	width: 350px;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-}
-.uelai{
-	width: 300px;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-}
-.annuqu{
-	width: 170px;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-	/* margin-right: 20px; */
-}
-.xiaohx{
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	width: 250px;
-}
-.zhongxh{
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	width: 350px;
-}
-.xiaohengx{
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	width: 20%;
-}
-.scriqlan{
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	width: 380px;
-}
-.biaoqian{
-	width: 80px;
-	font-size: 12px;
-	text-align: right;
-	padding-right: 10px;
-}
-.xxmimgc{
-	width: 100px;
-	font-size: 12px;
-	text-align: right;
-	padding-right: 10px;
-}
-.riqicd{
-	width: 250px;
-}
-.cintpu{
-	width: 230px;
-}
-.duannp{
-	width: 150px;
-}
-.shurlan{
-	width: 170px;
-}
-.dubuqur{
-	width: 100%;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-}
-.duancx{
-	width: 15%;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-	/* background-color: aquamarine; */
-}
-.qitalan{
-	width: 250px;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-	/* background-color: aquamarine; */
-}
-.ddksii{
-	width: 20%;
-	display: flex;
-	align-items: center;
-	justify-content: flex-end;
-	/* background-color: aquamarine; */
-}
-.zjiang{
-	padding-left: 125px;
-}

+ 0 - 61
foodie_sj_vue/src/router/index.js

@@ -1,61 +0,0 @@
-import Vue from 'vue'
-import VueRouter from 'vue-router'
-Vue.use(VueRouter)
-
-const routes = [
-	{
-	  path: '/',
-	  name: 'about',
-	  component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
-	},
-	{
-		path: '/',
-		name: 'Manage',
-		component: ()=>import('../views/Manage.vue'),
-		redirect:"/index",
-		children:[
-			{
-				path: 'index',
-				name: 'index',
-				component: ()=>import('../views/index.vue'),
-			},
-			{
-				path: 'acidrollingcapacity',
-				name: 'AcidrollingCapacity',
-				component: ()=>import('../views/AcidrollingCapacity.vue'),
-			},
-			{
-				path: 'acidrollingplan',
-				name: 'AcidrollingPlan',
-				component: ()=>import('../views/AcidrollingPlan.vue'),
-			},
-			{
-				path: 'acidrollingactual',
-				name: 'AcidrollingActual',
-				component: ()=>import('../views/AcidrollingActual.vue'),
-			},
-			{
-				path: 'promotion',
-				name: 'Promotion',
-				component: ()=>import('../views/Promotion.vue'),
-			},{
-				path: 'quanyi',
-				name: 'Quanyi',
-				component: ()=>import('../views/Quanyi.vue'),
-			},
-			{
-				path: 'review',
-				name: 'Review',
-				component: ()=>import('../views/Review.vue'),
-			}
-		]
-	}
-]
-
-const router = new VueRouter({
-  mode: 'hash',
-  base: process.env.BASE_URL,
-  routes
-})
-
-export default router

+ 0 - 30
foodie_sj_vue/src/router/jsencrypt.js

@@ -1,30 +0,0 @@
-import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
-
-// 密钥对生成 http://web.chacuo.net/netrsakeypair
-
-const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
-  'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
-
-const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
-  '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
-  'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
-  'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
-  'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
-  'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
-  'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
-  'UP8iWi1Qw0Y='
-
-// 加密
-export function encrypt(txt) {
-  const encryptor = new JSEncrypt()
-  encryptor.setPublicKey(publicKey) // 设置公钥
-  return encryptor.encrypt(txt) // 对数据进行加密
-}
-
-// 解密
-export function decrypt(txt) {
-  const encryptor = new JSEncrypt()
-  encryptor.setPrivateKey(privateKey) // 设置私钥
-  return encryptor.decrypt(txt) // 对数据进行解密
-}
-

+ 0 - 76
foodie_sj_vue/src/router/request.js

@@ -1,76 +0,0 @@
-import axios from 'axios'
-import {Loading, Message} from "element-ui";
-import {blobValidate, tansParams} from "@/utils/ruoyi";
-import errorCode from "@/utils/errorCode";
-import { saveAs } from 'file-saver'
-
-const request = axios.create({
-	// 从环境变量获取baseURL,如果没有设置则使用默认值
-    baseURL: process.env.VUE_APP_BASE_URL ,
-	timeout: 5000
-})
-
-// request 拦截器
-// 可以自请求发送前对请求做一些处理
-// 比如统一加token,对请求参数统一加密
-request.interceptors.request.use(config => {
-	config.headers['Content-Type'] = "application/json";
-	if(config.headers.isToken){
-		config.headers['token'] = localStorage.getItem('token');  // 设置请求头
-	}
-    return config
-}, error => {
-    return Promise.reject(error)
-});
-
-// response 拦截器
-// 可以在接口响应后统一处理结果
-request.interceptors.response.use(
-    response => {
-        let res = response.data;
-        // 如果是返回的文件
-        if (response.config.responseType === 'blob') {
-            return res
-        }
-        // 兼容服务端返回的字符串数据
-        if (typeof res === 'string') {
-            res = res ? JSON.parse(res) : res
-        }
-        return res;
-    },
-    error => {
-        // console.log('err' + error) // for debug
-        return Promise.reject(error)
-    }
-)
-let downloadLoadingInstance;
-export function download(url, params, filename, config,t) {
-    const safeT = t || ((key) => key); // 如果t不存在,直接返回key
-    downloadLoadingInstance = Loading.service({ text: 'Loading', spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
-    return request.post(url, params, {
-        // transformRequest: [(params) => { return tansParams(params) }],
-        params:params,
-        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
-        responseType: 'blob',
-        ...config
-    }).then(async (data) => {
-        const isBlob = blobValidate(data);
-        if (isBlob) {
-            const blob = new Blob([data])
-            saveAs(blob, filename)
-        } else {
-            const resText = await data.text();
-            const rspObj = JSON.parse(resText);
-            const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
-            Message.error(errMsg);
-        }
-        downloadLoadingInstance.close();
-    }).catch((r) => {
-        console.error(r)
-        Message.error('Error')
-        downloadLoadingInstance.close();
-    })
-}
-
-export default request
-

+ 0 - 3
foodie_sj_vue/src/utils/Bus.js

@@ -1,3 +0,0 @@
-import Vue from 'vue'
-const Bus = new Vue()
-export default Bus

+ 0 - 6
foodie_sj_vue/src/utils/errorCode.js

@@ -1,6 +0,0 @@
-export default {
-    '401': '认证失败,无法访问系统资源',
-    '403': '当前操作没有权限',
-    '404': '访问资源不存在',
-    'default': '系统未知错误,请反馈给管理员'
-}

+ 0 - 13
foodie_sj_vue/src/utils/i18n.js

@@ -1,13 +0,0 @@
-// 定义generateTitle 函数
-
-export function generateTitle(title) {
-  const hasKey = this.$te('dongtai.' + title)
-
-  if (hasKey) {
-    // $t :this method from vue-i18n, inject in @/lang/index.js
-    const translatedTitle = this.$t('dongtai.' + title)
-
-    return translatedTitle
-  }
-  return title
-}

+ 0 - 233
foodie_sj_vue/src/utils/ruoyi.js

@@ -1,233 +0,0 @@
-
-
-/**
- * 通用js方法封装处理
- * Copyright (c) 2019 ruoyi
- */
-
-// 日期格式化
-export function parseTime(time, pattern) {
-    if (arguments.length === 0 || !time) {
-        return null
-    }
-    const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
-    let date
-    if (typeof time === 'object') {
-        date = time
-    } else {
-        if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
-            time = parseInt(time)
-        } else if (typeof time === 'string') {
-            time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
-        }
-        if ((typeof time === 'number') && (time.toString().length === 10)) {
-            time = time * 1000
-        }
-        date = new Date(time)
-    }
-    const formatObj = {
-        y: date.getFullYear(),
-        m: date.getMonth() + 1,
-        d: date.getDate(),
-        h: date.getHours(),
-        i: date.getMinutes(),
-        s: date.getSeconds(),
-        a: date.getDay()
-    }
-    const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
-        let value = formatObj[key]
-        // Note: getDay() returns 0 on Sunday
-        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
-        if (result.length > 0 && value < 10) {
-            value = '0' + value
-        }
-        return value || 0
-    })
-    return time_str
-}
-
-// 表单重置
-export function resetForm(refName) {
-    if (this.$refs[refName]) {
-        this.$refs[refName].resetFields();
-    }
-}
-
-// 添加日期范围
-export function addDateRange(params, dateRange, propName) {
-    let search = params;
-    search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
-    dateRange = Array.isArray(dateRange) ? dateRange : [];
-    if (typeof (propName) === 'undefined') {
-        search.params['beginTime'] = dateRange[0];
-        search.params['endTime'] = dateRange[1];
-    } else {
-        search.params['begin' + propName] = dateRange[0];
-        search.params['end' + propName] = dateRange[1];
-    }
-    return search;
-}
-
-// 回显数据字典
-export function selectDictLabel(datas, value) {
-    if (value === undefined) {
-        return "";
-    }
-    var actions = [];
-    Object.keys(datas).some((key) => {
-        if (datas[key].value == ('' + value)) {
-            actions.push(datas[key].label);
-            return true;
-        }
-    })
-    if (actions.length === 0) {
-        actions.push(value);
-    }
-    return actions.join('');
-}
-
-// 回显数据字典(字符串、数组)
-export function selectDictLabels(datas, value, separator) {
-    if (value === undefined || value.length ===0) {
-        return "";
-    }
-    if (Array.isArray(value)) {
-        value = value.join(",");
-    }
-    var actions = [];
-    var currentSeparator = undefined === separator ? "," : separator;
-    var temp = value.split(currentSeparator);
-    Object.keys(value.split(currentSeparator)).some((val) => {
-        var match = false;
-        Object.keys(datas).some((key) => {
-            if (datas[key].value == ('' + temp[val])) {
-                actions.push(datas[key].label + currentSeparator);
-                match = true;
-            }
-        })
-        if (!match) {
-            actions.push(temp[val] + currentSeparator);
-        }
-    })
-    return actions.join('').substring(0, actions.join('').length - 1);
-}
-
-// 字符串格式化(%s )
-export function sprintf(str) {
-    var args = arguments, flag = true, i = 1;
-    str = str.replace(/%s/g, function () {
-        var arg = args[i++];
-        if (typeof arg === 'undefined') {
-            flag = false;
-            return '';
-        }
-        return arg;
-    });
-    return flag ? str : '';
-}
-
-// 转换字符串,undefined,null等转化为""
-export function parseStrEmpty(str) {
-    if (!str || str == "undefined" || str == "null") {
-        return "";
-    }
-    return str;
-}
-
-// 数据合并
-export function mergeRecursive(source, target) {
-    for (var p in target) {
-        try {
-            if (target[p].constructor == Object) {
-                source[p] = mergeRecursive(source[p], target[p]);
-            } else {
-                source[p] = target[p];
-            }
-        } catch (e) {
-            source[p] = target[p];
-        }
-    }
-    return source;
-};
-
-/**
- * 构造树型结构数据
- * @param {*} data 数据源
- * @param {*} id id字段 默认 'id'
- * @param {*} parentId 父节点字段 默认 'parentId'
- * @param {*} children 孩子节点字段 默认 'children'
- */
-export function handleTree(data, id, parentId, children) {
-    let config = {
-        id: id || 'id',
-        parentId: parentId || 'parentId',
-        childrenList: children || 'children'
-    };
-
-    var childrenListMap = {};
-    var nodeIds = {};
-    var tree = [];
-
-    for (let d of data) {
-        let parentId = d[config.parentId];
-        if (childrenListMap[parentId] == null) {
-            childrenListMap[parentId] = [];
-        }
-        nodeIds[d[config.id]] = d;
-        childrenListMap[parentId].push(d);
-    }
-
-    for (let d of data) {
-        let parentId = d[config.parentId];
-        if (nodeIds[parentId] == null) {
-            tree.push(d);
-        }
-    }
-
-    for (let t of tree) {
-        adaptToChildrenList(t);
-    }
-
-    function adaptToChildrenList(o) {
-        if (childrenListMap[o[config.id]] !== null) {
-            o[config.childrenList] = childrenListMap[o[config.id]];
-        }
-        if (o[config.childrenList]) {
-            for (let c of o[config.childrenList]) {
-                adaptToChildrenList(c);
-            }
-        }
-    }
-    return tree;
-}
-
-/**
- * 参数处理
- * @param {*} params  参数
- */
-export function tansParams(params) {
-    let result = ''
-    for (const propName of Object.keys(params)) {
-        const value = params[propName];
-        var part = encodeURIComponent(propName) + "=";
-        if (value !== null && value !== "" && typeof (value) !== "undefined") {
-            if (typeof value === 'object') {
-                for (const key of Object.keys(value)) {
-                    if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
-                        let params = propName + '[' + key + ']';
-                        var subPart = encodeURIComponent(params) + "=";
-                        result += subPart + encodeURIComponent(value[key]) + "&";
-                    }
-                }
-            } else {
-                result += part + encodeURIComponent(value) + "&";
-            }
-        }
-    }
-    return result
-}
-
-// 验证是否为blob格式
-export function blobValidate(data) {
-    return data.type !== 'application/json'
-}

+ 0 - 119
foodie_sj_vue/src/views/AboutView.vue

@@ -1,119 +0,0 @@
-<template>
-  <div class="about">
-		<img class="lupian" src="../assets/bag.jpg" alt=""/>
-		<!-- <el-image class="lupian"  src="../assets/bag.jpg" alt=""></el-image> -->
-		<div class="dengluk">
-			<h3 style="margin-bottom: 20px;">{{$t('loding.cte')}}</h3>
-			<div style="display: flex;align-items: center;font-size: 13px;justify-content: space-between;width: 325px;">
-				<div>{{$t('loding.lang')}}</div>
-				<i18n-select></i18n-select>
-			</div>
-			<div class="shulank">
-				<div class="hengxk">
-					<i class="el-icon-user" style="color: #505050; margin-right: 10px;"></i>
-					<el-input v-model="name" :placeholder="$t('loding.username')" style="width: 300px;"></el-input>
-				</div>
-				<div class="hengxk" style="margin-top: 20px;">
-					<i class="el-icon-unlock" style="color: #505050; margin-right: 10px;"></i>
-					<el-input v-model="pad" :placeholder="$t('loding.pasd')" show-password style="width: 300px;"></el-input>
-				</div>
-			</div>
-			<el-button type="primary" style="margin-top: 10px; width: 300px;height: 40px;" @click="gotiaozhuan">{{$t('loding.logng')}}</el-button>
-		</div>
-  </div>
-</template>
-<script>
-	import {loding,getuser} from '@/api/loding';
-	import { encrypt,decrypt } from '@/router/jsencrypt';
-	import i18nSelect from "../components/i18n.vue"
-	export default{
-		components: { i18nSelect },
-		name:"AboutView",
-		data(){
-			return {
-				name:'',
-				pad:''
-			}
-		},
-		created() {
-			this.getloduser();
-      i18nSelect.created()
-		},
-		methods:{
-			getloduser(){
-				getuser().then(response => {
-					// console.log("获取用户",response);
-					if(response.code==200){
-						localStorage.setItem('user', JSON.stringify(response.data));
-						this.$router.push('/index');
-					}
-				});
-			},
-			gotiaozhuan(){
-				if(this.name==''){
-					this.$message({
-					  message:this.$t('loding.txuse'),
-					  type: 'warning'
-					});
-					return
-				}
-				if(this.pad==''){
-					this.$message({
-					  message: this.$t('loding.txpad'),
-					  type: 'warning'
-					});
-					return
-				}
-				loding({
-					userName:this.name,
-					password:encrypt(this.pad),
-					cid:''
-				}).then(response => {
-					console.log("请求数据",response);
-					if(response.code==200){
-						localStorage.setItem('token', response.token);
-						localStorage.setItem('user', JSON.stringify(response.data));
-						this.$router.push('/index');
-					}else{
-						this.$message.error(response.msg);
-					}
-				});
-			}
-		}
-	}
-</script>
-
-<style>
-	.about{
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		width: 100vw;
-		height: 100vh;
-	}
-	.shulank{
-		margin: 20px 0;
-	}
-	.hengxk{
-		display: flex;
-		align-items: center;
-	}
-	.dengluk{
-		position: absolute;
-		z-index: 999;
-		width: 400px;
-		background-color: rgba(255, 255, 255, 0.8);
-		border-radius: 10px;
-		padding: 30px;
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-	}
-	.lupian{
-		width: 100vw;
-		height: 100vh;
-		object-fit: cover;
-		/* Sobject-position: 20% 20%; */
-	}
-</style>

+ 0 - 555
foodie_sj_vue/src/views/AcidrollingActual.vue

@@ -1,555 +0,0 @@
-<template>
-	<div>
-		<el-breadcrumb separator="/">
-		  <el-breadcrumb-item :to="{ path: '/' }">{{$t('foots.home')}}</el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('foots.Management')}}</el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('foots.Commodityfood')}}</el-breadcrumb-item>
-		</el-breadcrumb>
-		<div style="margin-top: 30px;display: flex;align-items: center;">
-			<el-button v-for="item in mdlist" :type="dqmd==item.id?'primary':'info'" class="biaoqian" @click="xuanzhemd(item.id)">{{item.posName}}</el-button>
-		</div>
-		<div style="display: flex;width: 100%;margin-top: 20px;">
-			<div style="width: 200px;background-color: #f7f7f7;margin-right: 20px;padding: 20px;">
-				<div style="font-size: 13px;font-weight: bold">{{$t('foots.classification')}}</div>
-				<div style="margin-top: 10px;">
-					<div :class="dqfl==item.id?'flxz':'flwx'" v-for="item in fllist" @click="xzfenlei(item.id)">{{item.name}}</div>
-				</div>
-			</div>
-			<div style="width: 100%;">
-				<el-row :gutter="10" style="margin-bottom: 10px;">
-				  <el-col :span="12" style="display: flex; align-items: center;">
-				    <el-input
-				      v-model="searchName"
-				      :placeholder="$t('foots.Enterproductname')"
-				      clearable
-				      style="width: 240px; margin-right: 12px;"
-				    />
-				    <el-button
-				      type="primary"
-				      icon="el-icon-search"
-				      @click="onSearch"
-				      style="margin-right: 8px;"
-				    >{{$t('foots.search')}}</el-button>
-				    <el-button
-				      type="default"
-				      icon="el-icon-refresh"
-				      @click="onReset"
-				    >{{$t('foots.reset') || '重置'}}</el-button>
-				  </el-col>
-				</el-row>
-				<el-row :gutter="10" style="margin-bottom: 20px;">
-				  <el-col :span="6">
-				    <el-button
-				      type="primary"
-				      plain
-				      icon="el-icon-plus"
-				      size="mini"
-					  @click="addfood"
-				    >{{$t('foots.addproduct')}}</el-button>
-				  </el-col>
-				</el-row>
-				<el-table  ref="filterTable" v-loading="loding"  :data="filteredTableData" :header-cell-style="{background:'#f0f0f0'}">
-					<el-table-column
-						prop="id"
-						label="id"
-					>
-					</el-table-column>
-					<el-table-column
-						prop="name"
-						:label="$t('foots.Tradename')"
-					>
-					</el-table-column>
-					<el-table-column
-						prop="image"
-						:label="$t('foots.Commoditypicture')"
-					>
-						<template slot-scope="scope">
-							<img style="width: 50px;height: 50px;" :src="seruer+scope.row.image" alt="" />
-						</template>
-					</el-table-column>
-					<el-table-column
-						prop="price"
-						:label="$t('foots.commodityprice')"
-					>
-					</el-table-column>
-					<el-table-column
-						prop="introduce"
-						:label="$t('foots.illustrate')"
-					>
-					</el-table-column>
-					<el-table-column
-						fixed="right"
-						:label="$t('foots.operate')"
-						:width="$t('loding.language')=='en'?'150':'100'">
-						<template slot-scope="scope">
-							<el-button @click="handleClick(scope.row)" type="text" size="small">{{$t('foots.modify')}}</el-button>
-							<el-button @click="delechansu(scope.row)" type="text" size="small">{{$t('foots.delete')}}</el-button>
-						</template>
-					</el-table-column>
-				</el-table>
-			</div>
-		</div>
-
-		<!-- 添加或修改门店分类对话框 -->
-		<el-dialog :title="text" :visible.sync="open" :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'690px':'600px'" append-to-body>
-		  <el-form ref="form" :model="form" :rules="rules" :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'170px':'80px'">
-			<el-form-item :label="$t('foots.Commoditypicture')" prop="image">
-			    <el-upload
-			      class="avatar-uploader"
-			      :action="seruer+'/utils/Upload'"
-			      :show-file-list="false"
-			      :on-success="handleAvatarSuccess"
-			      :before-upload="beforeAvatarUpload">
-			      <img v-if="form.image" :src="seruer+form.image" class="avatar">
-			      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-			    </el-upload>
-			</el-form-item>
-		    <el-form-item :label="$t('foots.Tradename')" prop="name">
-				<el-input v-model="form.name" :placeholder="$t('foots.Enterproductname')" />
-		    </el-form-item>
-			<el-form-item :label="$t('foots.commodityprice')" prop="price">
-				<el-input v-model="form.price" type="number" :placeholder="$t('foots.Enterproductprice')" />
-			</el-form-item>
-			<el-form-item :label="$t('foots.Attributes')" prop="sku">
-				<el-button type="primary" round @click="dakaitjlx">{{$t('foots.AddType')}}</el-button>
-				<div>
-					<div v-for="(item,idx) in form.sku" style="width: 400px;padding: 20px;background-color: #f7f7f7;margin-top: 10px;">
-						<div style="display: flex;align-items: center;justify-content: space-between;">
-							<div style="font-size: 15px;font-weight: bold;display: flex;">{{item.title}}
-								<div style="margin-left: 10px;">{{item.type==1?$t('foots.Radio'):$t('foots.multiplechoice')}}/{{item.state==2?$t('foots.optional'):$t('foots.required')}}</div>
-							</div>
-							<div style="display: flex;align-items: center;width: 60px;justify-content: space-between;">
-								<el-button  type="primary" icon="el-icon-plus" circle  @click="tanchuguige(idx)"></el-button>
-								<el-button type="danger" icon="el-icon-delete" circle @click="deleleixing(idx)"></el-button>
-							</div>
-						</div>
-						<div v-for="(cc,inx) in item.objects" style="background-color: #ffffff;padding: 10px 20px;margin-top: 10px;font-size: 13px;display: flex;align-items: center;justify-content: space-between;">
-							<div style="display: flex;align-items: center;justify-content: space-between;width: 280px;">
-								<div style="color: #4c4c4c;display: flex;">{{cc.name}}<div style="color: #9d9d9d;font-size: 10px;margin-left: 10px;">{{cc.note}}</div></div>
-								<div style="color: #ff5500;">{{cc.price}}</div>
-							</div>
-							<el-button type="danger" icon="el-icon-delete" circle @click="deleguige(idx,inx)"></el-button>
-						</div>
-					</div>
-				</div>
-			</el-form-item>
-			<el-form-item :label="$t('foots.Introduction')" prop="introduce">
-				<el-input v-model="form.introduce" type="textarea"  :placeholder="$t('foots.EnterIntroduction')" />
-			</el-form-item>
-			<el-form-item :label="$t('foots.Dorecommendit')" prop="recommend">
-				<el-switch
-				    v-model="form.recommend"
-				    active-color="#55aaff"
-				    inactive-color="#d5d5d5"
-				    :active-value="1"
-				    :inactive-value="0">
-				  </el-switch>
-			</el-form-item>
-			<el-form-item :label="$t('foots.Productsorting')" prop="sort">
-				<el-input v-model="form.sort" type="number"  :placeholder="$t('foots.Anynumber')" />
-			</el-form-item>
-		  </el-form>
-		  <div slot="footer" class="dialog-footer">
-		    <el-button type="primary" @click="tijiaosb">{{$t('foots.determine')}}</el-button>
-		    <el-button @click="cancel">{{$t('foots.cancellation')}}</el-button>
-		  </div>
-		</el-dialog>
-		<!-- 添加类型弹出框 -->
-		<el-dialog :title="$t('foots.AddType')" :visible.sync="lxop" width="600px" append-to-body>
-			<el-form ref="splx" :model="splx" label-width="200px">
-				<el-form-item :label="$t('foots.typename')" prop="title">
-					<el-input v-model="splx.title" :placeholder="$t('foots.InputMerchantType')" />
-				</el-form-item>
-				<el-form-item :label="$t('foots.Multiplechoices')" prop="type">
-					<el-radio v-model="splx.type" label="1">{{$t('foots.Radio')}}</el-radio>
-					<el-radio v-model="splx.type" label="2">{{$t('foots.multiplechoice')}}</el-radio>
-				</el-form-item>
-				<el-form-item :label="$t('foots.Isitmandatory')" prop="state">
-					<el-radio v-model="splx.state" label="1">{{$t('foots.required')}}</el-radio>
-					<el-radio v-model="splx.state" label="2">{{$t('foots.optional')}}</el-radio>
-				</el-form-item>
-			</el-form>
-			<div slot="footer" class="dialog-footer">
-			  <el-button type="primary" @click="tianzspleix">{{$t('foots.determine')}}</el-button>
-			  <el-button @click="lxquxxiao">{{$t('foots.cancellation')}}</el-button>
-			</div>
-		</el-dialog>
-		<!-- 添加类型弹出框 -->
-		<el-dialog :title="$t('foots.Addspecifications')" :visible.sync="ggop" width="600px" append-to-body>
-			<el-form ref="lxgg" :model="lxgg" label-width="200px">
-				<el-form-item :label="$t('foots.formname')" prop="name">
-					<el-input v-model="lxgg.name" :placeholder="$t('foots.Entercationname')" />
-				</el-form-item>
-				<el-form-item :label="$t('foots.Specificationprice')" prop="price">
-					<el-input v-model="lxgg.price" :placeholder="$t('foots.Enterandprices')" />
-				</el-form-item>
-				<el-form-item :label="$t('foots.description')" prop="note">
-					<el-input v-model="lxgg.note" type="textarea" :placeholder="$t('foots.Entercationiption')" />
-				</el-form-item>
-			</el-form>
-			<div slot="footer" class="dialog-footer">
-			  <el-button type="primary" @click="tianjguige">{{$t('foots.determine')}}</el-button>
-			  <el-button @click="quxiaguige">{{$t('foots.cancellation')}}</el-button>
-			</div>
-		</el-dialog>
-	</div>
-</template>
-
-<script>
-	import {storelistlist,getordfenlei,getidlist,setposfood,delefood} from '@/api/food';
-	import Bus from '../utils/Bus.js'
-	export default{
-		name:"AcidrollingCapacity",
-		data(){
-			return {
-				seruer: process.env.VUE_APP_BASE_URL,
-				loding:false,
-				mdlist:[],
-				fllist:[],
-				dqmd:0,
-				dqfl:0,
-				tableData:[],
-				form:{},
-				text:'',
-				open:false,
-				lxop:false,
-				ggop:false,
-				splx:{},
-				lxgg:{},
-				ggindex:0,
-				language:this.$t('loding.lass'),
-				searchName: '',
-				// 表单校验
-				rules: {
-				  image: [
-				    { required: true, message: this.$t('foots.Imagebeempty'), trigger: "blur" }
-				  ],
-				  name: [
-				    { required: true, message:this.$t('foots.Namebeempty'), trigger: "blur" }
-				  ],
-				  price: [
-				    { required: true, message: this.$t('foots.Pricebeempty'), trigger: "blur" }
-				  ],
-				},
-			}
-		},
-		created() {
-			var that = this;
-			that.getstorelist();
-			Bus.$on('l18zh',function(res){
-				that.language = res;
-				that.dqmd = that.dqmd==0?0:that.dqmd;
-				that.getlenlei(that.dqmd);
-			})
-		},
-		methods:{
-			format(str) {
-			  var arr = [];
-			    var counter = 0;
-			    str = (str || 0).toString().split("");
-			    for (var i = str.length - 1; i >= 0; i--) {
-			      counter++;
-			      arr.unshift(str[i]);
-			      if (!(counter % 3) && i !== 0) {
-			        arr.unshift(",");
-			      }
-			    }
-			    return arr.join("");
-			},
-			// 提交添加商品
-			tijiaosb(){
-				this.form.language = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-				this.$refs["form"].validate(valid => {
-				  if (valid) {
-					setposfood(this.form).then(res=>{
-						// console.log('操作成功',res)
-						if(res.code==200){
-							this.getfoodlist(this.dqfl);
-							this.open = false;
-							this.reset();
-						}
-					})
-				  }
-				});
-			},
-			//添加商品规格
-			tianjguige(){
-				if(this.lxgg.name==null){
-					this.$message.error(this.$t('foots.Thenamebeempty'));
-					return
-				}
-				this.form.sku[this.ggindex].objects = this.form.sku[this.ggindex].objects.concat(this.lxgg);
-				this.quxiaguige();
-			},
-			//添加商品类型
-			tianzspleix(){
-				if(this.splx.title==null){
-					this.$message.error(this.$t('foots.Typenamebeempty'));
-					return
-				}
-				this.form.sku = this.form.sku.concat(this.splx);
-				this.lxquxxiao();
-			},
-			// 删除商品类型
-			deleleixing(idx){
-				this.$confirm(this.$t('foots.Confirmdeletion'), this.$t('foots.prompt'), {
-					confirmButtonText: this.$t('foots.determine'),
-					cancelButtonText: this.$t('foots.cancellation'),
-					type: 'warning'
-				}).then(() => {
-					if(this.form.sku[idx].objects.length>0){
-						this.$message.error(this.$t('foots.Unabletodelete'));
-						return
-					}
-					this.form.sku.splice(idx, 1);
-				}).catch(() => {
-
-				});
-			},
-			deleguige(idx,inx){
-				this.$confirm( this.$t('foots.DeleteSpecification'), this.$t('foots.prompt'), {
-					confirmButtonText: this.$t('foots.determine'),
-					cancelButtonText: this.$t('foots.cancellation'),
-					type: 'warning'
-				}).then(() => {
-					this.form.sku[idx].objects.splice(inx, 1);
-				}).catch(() => {
-
-				});
-			},
-			tanchuguige(idx){
-				this.czguige();
-				this.ggindex = idx;
-				this.ggop = true;
-			},
-			//关闭规格输入
-			quxiaguige(){
-				this.ggop = false;
-				this.ggindex = 0;
-				this.czguige();
-			},
-			czguige(){
-				this.lxgg={
-					name:null,
-					note:null,
-					price:null,
-					state:0
-				}
-			},
-			czlex(){
-				this.splx={
-					title:null,
-					type:'1',
-					state:'1',
-					objects:[]
-				}
-			},
-			//弹出添加类型
-			dakaitjlx(){
-				this.czlex();
-				this.lxop = true;
-			},
-			getstorelist(){
-				storelistlist().then(res=>{
-					// console.log('门店列表',res)
-					this.dqmd = this.dqmd==0?res.data.records[0].id:this.dqmd;
-					this.mdlist = res.data.records;
-					this.getlenlei(this.dqmd);
-				})
-			},
-			//选择门店
-			xuanzhemd(id){
-				this.dqmd = id;
-				this.getlenlei(id);
-			},
-			// 选择分类
-			xzfenlei(id){
-				this.dqfl = id;
-				this.getfoodlist(this.dqfl);
-			},
-			//获取分类
-			getlenlei(id){
-				var lang = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-				getordfenlei(id,lang).then(res=>{
-					// console.log('分类',res)
-          if(res.data.length>0) {
-            this.dqfl = res.data[0].id;
-            this.fllist = res.data;
-            this.getfoodlist(this.dqfl);
-          }
-				})
-			},
-			//获取商品
-			getfoodlist(id){
-				this.loding = true;
-				var lang = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-				getidlist(id,lang,this.searchName).then(res=>{
-					// console.log('商品列表',res)
-					var list = res.data;
-					for(let i=0;i<list.length;i++){
-					  list[i].price = this.format(list[i].price);
-					}
-					this.tableData = list;
-					this.loding = false;
-				})
-			},
-			reset() {
-				this.form = {
-					flId: this.dqfl,
-					mdid: this.dqmd,
-					name:null,
-					image:null,
-					price:null,
-					introduce:null,
-					recommend:0,
-					sort:null,
-					language:null,
-					sku:[]
-				};
-			},
-			// 添加商品
-			addfood(){
-				this.reset();
-				this.text =this.$t('foots.addproduct');
-				this.open = true;
-
-			},
-			handleClick(res){
-				this.reset();
-				this.text = this.$t('foots.Modifyproduct');
-				this.form = {
-					id:res.id,
-					flId: res.fenlei.id,
-					mdid: res.store.id,
-					name:res.name,
-					image:res.image,
-					price:res.price.replace(/,/g, ""),
-					introduce:res.introduce,
-					recommend:res.recommend,
-					sort:res.sort,
-					sku:res.foodSku
-				};
-				this.open = true;
-			},
-			delechansu(e){
-				this.$confirm(this.$t('foots.Deletethisproduct'), this.$t('foots.prompt'), {
-					confirmButtonText: this.$t('foots.determine'),
-					cancelButtonText: this.$t('foots.cancellation'),
-					type: 'warning'
-				}).then(() => {
-					delefood(e.id).then(res=>{
-						// console.log('删除',res);
-						if(res.code==200){
-							this.getfoodlist(this.dqfl);
-							this.$message({
-								type: 'success',
-								message:  this.$t('foots.successful')
-							});
-						}else{
-							this.$message({
-								type: 'info',
-								message:  this.$t('foots.Deletefailed')
-							});
-						}
-
-					})
-				}).catch(() => {
-					this.$message({
-						type: 'info',
-						message:  this.$t('foots.undelete')
-					});
-				});
-			},
-			// 取消添加
-			cancel(){
-				this.open = false;
-				this.reset();
-			},
-			lxquxxiao(){
-				this.lxop = false;
-				this.czlex();
-			},
-			handleAvatarSuccess(res, file) {
-				// this.upimg = URL.createObjectURL(file.raw);
-				this.form.image = file.response.data;
-				// console.log('上传图片',file.response);
-
-			},
-			beforeAvatarUpload(file) {
-				const isJPG = file.type === 'image/jpeg';
-				const isLt2M = file.size / 1024 / 1024 < 2;
-
-				if (!isJPG) {
-				  this.$message.error(this.$t('foots.ItcanonlyJPG'));
-				}
-				if (!isLt2M) {
-				  this.$message.error(this.$t('foots.Cannotexceed'));
-				}
-				return isJPG && isLt2M;
-			},
-			onSearch() {
-				// 目前先前端过滤
-				 this.getfoodlist(this.dqfl);
-			},
-			onReset() {
-				this.searchName = '';
-				this.onSearch();
-			},
-		},
-		computed: {
-			filteredTableData() {
-				 return this.tableData;
-				// return this.tableData.filter(item => item.name && item.name.indexOf(this.searchName) !== -1);
-			}
-		},
-	}
-</script>
-
-<style>
-	.biaoqian{
-		width: 180px;
-		height: 30px;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		margin-right: 10px;
-	}
-	.flxz{
-		padding: 10px 20px;
-		font-size: 12px;
-		background-color: #ffffff;
-		border-radius: 5px;
-		color: #ff557f;
-		font-weight: bold;
-
-	}
-	.flwx{
-		padding: 10px 20px;
-		font-size: 12px;
-		color: #acacac;
-
-	}
-	.avatar-uploader .el-upload {
-	    border: 1px dashed #d9d9d9;
-	    border-radius: 6px;
-	    cursor: pointer;
-	    position: relative;
-	    overflow: hidden;
-	  }
-	  .avatar-uploader .el-upload:hover {
-	    border-color: #409EFF;
-	  }
-	  .avatar-uploader-icon {
-	    font-size: 28px;
-	    color: #8c939d;
-	    width: 100px;
-	    height: 100px;
-	    line-height: 100px;
-	    text-align: center;
-	  }
-	  .avatar {
-	    width: 100px;
-	    height: 100px;
-	    display: block;
-	  }
-</style>

+ 0 - 657
foodie_sj_vue/src/views/AcidrollingCapacity.vue

@@ -1,657 +0,0 @@
-<template>
-	<div>
-		<el-breadcrumb separator="/">
-		  <el-breadcrumb-item :to="{ path: '/' }">{{$t('mendian.home')}}</el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('mendian.Management')}}</el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('mendian.StoreList')}}</el-breadcrumb-item>
-		</el-breadcrumb>
-		<el-row :gutter="10" style="margin-top: 20px;margin-bottom: 20px;">
-		  <el-col :span="1.5">
-		    <el-button
-		      type="primary"
-		      plain
-		      icon="el-icon-plus"
-		      size="mini"
-		      @click="handleAdd"
-		    >{{$t('mendian.AddStore')}}</el-button>
-		  </el-col>
-		</el-row>
-		<el-table ref="filterTable" v-loading="loding"  :data="tableData" :header-cell-style="{background:'#f0f0f0'}">
-			<el-table-column
-				prop="id"
-				label="id"
-			>
-			</el-table-column>
-			<el-table-column
-				prop="image"
-				:label="$t('mendian.StoreCover')"
-			>
-				<template slot-scope="scope">
-					<img style="width: 50px;height: 50px;" :src="seruer+scope.row.image" alt="" />
-				</template>
-			</el-table-column>
-			<el-table-column
-				prop="posName"
-				:label="$t('mendian.StoreName')"
-				width="200"
-			>
-			</el-table-column>
-			<el-table-column
-				prop="posPrice"
-				:label="$t('mendian.Startingprice')"
-				width="200"
-			>
-			</el-table-column>
-<!--			<el-table-column-->
-<!--				prop="businessHours"-->
-<!--				:label="$t('mendian.businesshours')"-->
-<!--			>-->
-<!--			</el-table-column>-->
-			<el-table-column
-				prop="area"
-				:label="$t('mendian.area')"
-			>
-			</el-table-column>
-			<el-table-column
-				prop="telephone"
-				:label="$t('mendian.Telephone')"
-				width="200"
-			>
-			</el-table-column>
-			<el-table-column
-				fixed="right"
-				:label="$t('mendian.operate')"
-				width="120">
-				<template slot-scope="scope">
-					<el-button @click="handleClick(scope.row)" type="text" size="small">{{$t('mendian.modify')}}</el-button>
-					<el-button @click="delechansu(scope.row)" type="text" size="small">{{$t('mendian.delete')}}</el-button>
-				</template>
-			</el-table-column>
-		</el-table>
-		<div style="width: 100%;display: flex;justify-content: flex-end;">
-			<el-pagination
-				@size-change="handleSizeChange"
-				@current-change="handleCurrentChange"
-				:current-page="queryParams.page"
-				:page-size="queryParams.size"
-				layout="total, prev, pager, next"
-				:total="total">
-			</el-pagination>
-		</div>
-		<!-- 添加或修改门店分类对话框 -->
-		<el-dialog :title="text" :visible.sync="open" :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'650px':'600px'" append-to-body>
-		  <el-form ref="form" :model="form" :rules="rules" :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'180px':'100px'">
-			<el-form-item :label="$t('mendian.logo')" prop="logo">
-			    <el-upload
-			      class="avatar-uploader"
-			      :action="seruer+'/utils/Upload'"
-			      :show-file-list="false"
-			      :on-success="handleAvatarlogo"
-			      :before-upload="beforeAvatarUpload">
-			      <img v-if="form.logo" :src="seruer+form.logo" class="avatar">
-			      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-			    </el-upload>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.StoreCover')" prop="image">
-			    <el-upload
-			      class="avatar-uploader"
-			      :action="seruer+'/utils/Upload'"
-			      :show-file-list="false"
-			      :on-success="handleAvatarSuccess"
-			      :before-upload="beforeAvatarUpload">
-			      <img v-if="form.image" :src="seruer+form.image" class="avatar">
-			      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-			    </el-upload>
-			</el-form-item>
-		    <el-form-item :label="$t('mendian.StoreName')" prop="posName">
-				<el-input v-model="form.posName" :placeholder="$t('mendian.Enterstorename')" />
-		    </el-form-item>
-		    <el-form-item :label="$t('mendian.address')" prop="address">
-		    	<div style="display: flex;align-items: center;">
-					<el-input v-model="form.address" :placeholder="$t('mendian.InputAddress')" />
-					<i style="color: #55aaff; margin-left: 10px;font-size: 25px;" class="el-icon-location"  @click="xuanzhemap"></i>
-				</div>
-		    </el-form-item>
-			<el-form-item :label="$t('mendian.coordinate')"  prop="longitude">
-				<div style="display: flex;align-items: center;" @click="xuanzhemap">
-					<div>{{form.longitude==null?$t('mendian.Positioningobtaincoordinates'):form.longitude+','+form.latitude}}</div>
-				</div>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.Storetype')" prop="type">
-				<el-radio v-model="form.type" :label="0" @change="handleTypeChange">{{$t('mendian.Restaurant')}}</el-radio>
-				<el-radio v-model="form.type" :label="1" @change="handleTypeChange">{{$t('mendian.Supermarket')}}</el-radio>
-			</el-form-item>
-			<el-form-item :label="'是否关联夜市'" prop="isNightMarket">
-				<el-radio v-model="form.isNightMarket" :label="1">是</el-radio>
-				<el-radio v-model="form.isNightMarket" :label="0">否</el-radio>
-			</el-form-item>
-			<el-form-item v-if="form.isNightMarket === 1" :label="'夜市'" prop="nightMarketId">
-				<el-select v-model="form.nightMarketId" placeholder="请选择夜市">
-					<el-option
-						v-for="item in nightMarketList"
-						:key="item.userId"
-						:label="item.nickName"
-						:value="item.userId">
-					</el-option>
-				</el-select>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.Startingprice')" prop="posPrice">
-				<el-input v-model="form.posPrice" :placeholder="$t('mendian.Fillintheprice')" />
-			</el-form-item>
-			<el-form-item :label="$t('mendian.Telephone')" prop="telephone">
-				<el-input v-model="form.telephone" :placeholder="$t('mendian.Fillphonenumber')" />
-			</el-form-item>
-			<el-form-item :label="$t('mendian.openingtime')" prop="businessHours">
-				<div v-for="(item, idx) in form.businessHours" :key="idx" style="display: flex; align-items: center; margin-bottom: 8px;">
-				  <el-time-picker
-					v-model="item.startTime"
-					:placeholder="$t('mendian.FillopenBusiness')"
-					value-format="HH:mm"
-					format="HH:mm"
-					style="width: 110px;"
-				  />
-				  <span style="margin: 0 8px;">—</span>
-				  <el-time-picker
-					v-model="item.endTime"
-					:placeholder="$t('mendian.FillwindingUp')"
-					value-format="HH:mm"
-					format="HH:mm"
-					style="width: 110px;"
-				  />
-				  <el-button
-					v-if="form.businessHours.length > 1"
-					icon="el-icon-minus"
-					type="danger"
-					size="mini"
-					@click="removeBusinessHour(idx)"
-					style="margin-left: 8px;"
-				  ></el-button>
-				</div>
-				<el-button
-				  icon="el-icon-plus"
-				  type="primary"
-				  size="mini"
-				  @click="addBusinessHour"
-				>{{$t('mendian.addTime')}}</el-button>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.classification')" prop="sort">
-				<el-select v-model="form.sort" multiple placeholder="请选择分类" @change="handleSortChange">
-				    <el-option
-				      v-for="item in fenlei"
-				      :key="item.id"
-				      :label="$t('loding.language')=='zh-CN'?item.name:$t('loding.language')=='en'?item.nameEn:$t('loding.language')=='zh-TW'?item.nameTw:item.nameVi"
-				      :value="item.id">
-				    </el-option>
-				</el-select>
-				<!-- 显示选中的分类名称 -->
-				<div v-if="selectedCategoryNames && selectedCategoryNames.length > 0" style="margin-top: 5px;">
-					<el-tag
-						v-for="(name, index) in selectedCategoryNames"
-						:key="index"
-						size="small"
-						style="margin-right: 5px; margin-bottom: 5px;">
-						{{ name }}
-					</el-tag>
-				</div>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.ServiceType')" prop="serverType">
-				<el-checkbox-group v-model="checkList">
-					<el-checkbox v-for="item in fwlxlist" :label="item.id" @change="huoqujieguo">{{$t('loding.language')=='zh-CN'?item.nameCn:$t('loding.language')=='en'?item.nameEn:$t('loding.language')=='zh-TW'?item.nameTw:item.nameVi}}</el-checkbox>
-				</el-checkbox-group>
-			</el-form-item>
-			<el-form-item :label="$t('mendian.state')" prop="state">
-				<el-radio v-model="form.state" :label="0">{{$t('mendian.trade')}}</el-radio>
-				<el-radio v-model="form.state" :label="1">{{$t('mendian.close')}}</el-radio>
-			</el-form-item>
-		  </el-form>
-		  <div slot="footer" class="dialog-footer">
-		    <el-button type="primary" @click="tijiaobaocun">{{$t('mendian.determine')}}</el-button>
-		    <el-button @click="cancel">{{$t('mendian.cancellation')}}</el-button>
-		  </div>
-		</el-dialog>
-		<!-- 地图 -->
-		<el-dialog :title="$t('mendian.selectaddress')" :visible.sync="opmap" width="1000px" append-to-body>
-			<googmap  mapID="googleMap" @golat="huichuandizhi"></googmap>
-			<div slot="footer" class="dialog-footer">
-				<el-button type="primary" @click="dituqiueing">{{$t('mendian.determine')}}</el-button>
-				<el-button @click="guanbimay">{{$t('mendian.cancellation')}}</el-button>
-			</div>
-		</el-dialog>
-	</div>
-</template>
-
-<script>
-import {
-  getfenlei,
-  storelistlist,
-  getAddr,
-  addmendian,
-  delemendian,
-  getfwleixing,
-  getNightMarketlist,
-  getfenleilistByTag
-} from '@/api/store';
-	import googmap from "@/components/googmap.vue";
-	export default{
-		name:"AcidrollingCapacity",
-		components:{
-			 googmap
-		},
-		data(){
-			return {
-				seruer: process.env.VUE_APP_BASE_API,
-				loding:false,
-				tableData:[],
-				total:0,
-				checkList:[],
-				//分页
-				queryParams: {
-				  page: 1,
-				  size: 10,
-				},
-				fenlei:[],
-				fwlxlist:[],
-				nightMarketList:[],
-				open:false,
-				opmap:false,
-				form:{
-					businessHours: [{ startTime: '', endTime: '' }]
-				},
-				user:{},
-				mdid:'',
-				// 表单校验
-				rules: {
-				  image: [
-				    { required: true, message:this.$t('mendian.Covercannotempty'), trigger: "blur" }
-				  ],
-				  posName: [
-				    { required: true, message: this.$t('mendian.Namecannotempty'), trigger: "blur" }
-				  ],
-				  address: [
-				    { required: true, message: this.$t('mendian.Addresscannotempty'), trigger: "blur" }
-				  ],
-				  longitude: [
-				    { required: true, message: this.$t('mendian.Coordinatescannotempty'), trigger: "blur" }
-				  ],
-				  sort: [
-				    {
-						type: 'array',
-						required: true,
-						message: this.$t('mendian.Classifiedmandatory'),
-						trigger: "change"
-					}
-				  ],
-				  serverType: [
-					{ required: true, message: this.$t('mendian.Selectservicetype'), trigger: "blur" }
-				  ],
-				  nightMarketId: [
-					{
-					  validator: (rule, value, callback) => {
-						if (this.form.isNightMarket === 1 && (!value || value === null)) {
-						  callback(new Error('请选择夜市'));
-						} else {
-						  callback();
-						}
-					},
-					trigger: 'change'
-				  }],
-				  businessHours: [
-					{
-					  validator: (rule, value, callback) => {
-						if (!value || value.length === 0) {
-						  callback(new Error(this.$t('mendian.zssjd')));
-						} else if (value.some(v => !v.startTime || !v.endTime)) {
-						  callback(new Error(this.$t('mendian.mgsjd')));
-						} else {
-						  callback();
-						}
-				  },
-				  trigger: 'change'
-				}]
-				},
-				mapaddress:null,
-				text: '',
-			}
-		},
-		computed: {
-			// 获取选中分类的名称列表
-			selectedCategoryNames() {
-				if (!this.form.sort || !Array.isArray(this.form.sort)) {
-					return [];
-				}
-				return this.form.sort.map(id => {
-					const category = this.fenlei.find(item => item.id === id);
-					if (category) {
-						return this.$t('loding.language')=='zh-CN'?category.name:this.$t('loding.language')=='en'?category.nameEn:this.$t('loding.language')=='zh-TW'?category.nameTw:category.nameVi;
-					}
-					return '';
-				}).filter(name => name);
-			}
-		},
-		created() {
-			this.getpinguilist();
-			this.getfuleix();
-			this.getNightMarketList();
-			this.user = JSON.parse(localStorage.getItem('user'));
-			// console.log('1111111111',this.user);
-		},
-		methods:{
-			huoqujieguo(){
-				this.form.serverType = this.checkList.length>0?JSON.stringify(this.checkList):null;
-				console.log(this.form.serverType)
-			},
-			delechansu(e){
-				this.$confirm(this.$t('mendian.youwanttodeleteit'), this.$t('mendian.prompt'), {
-					confirmButtonText: this.$t('mendian.determine'),
-					cancelButtonText: this.$t('mendian.cancellation'),
-					type: 'warning'
-				}).then(() => {
-					delemendian(e.id).then(res=>{
-						// console.log('删除',res);
-						if(res.code==200){
-							this.getpinguilist();
-							this.$message({
-								type: 'success',
-								message: this.$t('mendian.successful')
-							});
-						}else{
-							this.$message({
-								type: 'info',
-								message: this.$t('mendian.Deletefailed')
-							});
-						}
-
-					})
-				}).catch(() => {
-					this.$message({
-						type: 'info',
-						message: this.$t('mendian.undelete')
-					});
-				});
-
-			},
-			tijiaobaocun(){
-				this.$refs["form"].validate(valid => {
-				  if (valid) {
-					// 深拷贝 businessHours,去除响应式属性
-					const submitForm = { ...this.form };
-					submitForm.businessHours = JSON.parse(JSON.stringify(this.form.businessHours));
-					// 确保分类字段是英文逗号分隔的字符串格式
-					if (Array.isArray(submitForm.sort)) {
-						submitForm.sort = submitForm.sort.join(',');
-					}
-					console.log('发送到后端的数据:', submitForm);
-					console.log('分类字段格式:', submitForm.sort);
-					addmendian(submitForm).then(res=>{
-						// console.log('操作成功',res)
-						if(res.code==200){
-							this.getpinguilist();
-							this.open = false;
-							this.checkList = [];
-							this.reset();
-						}
-					})
-				  }
-				});
-
-			},
-			//地图回传地址
-			huichuandizhi(res){
-				console.log('地址回传',res);
-				console.log('回传数据类型:', typeof res);
-				console.log('回传数据内容:', JSON.stringify(res));
-				this.mapaddress = res;
-				console.log('设置后的mapaddress:', this.mapaddress);
-			},
-			// 修改门店
-			handleClick(res){
-				this.text = this.$t('mendian.ModifyStore');
-        console.log('修改门店',res);
-				this.form = res;
-				this.getfenleilistByTag();
-				// 确保夜市字段有默认值
-				if (this.form.isNightMarket === undefined || this.form.isNightMarket === null) {
-					this.form.isNightMarket = 0;
-				}
-				if (this.form.nightMarketId === undefined || this.form.nightMarketId === null) {
-					this.form.nightMarketId = null;
-				}
-				// 处理分类字段,如果是字符串则转换为数组
-				if (typeof this.form.sort === 'string') {
-					try {
-						// 尝试解析JSON格式
-						this.form.sort = JSON.parse(this.form.sort);
-					} catch(e) {
-						// 如果不是JSON格式,尝试按逗号分割
-						if (this.form.sort.includes(',')) {
-							this.form.sort = this.form.sort.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id));
-						} else {
-							this.form.sort = this.form.sort ? [parseInt(this.form.sort)] : [];
-						}
-					}
-				} else if (!Array.isArray(this.form.sort)) {
-					this.form.sort = this.form.sort ? [this.form.sort] : [];
-				}
-				this.checkList = JSON.parse(res.serverType);
-				if (res.businessHours && typeof res.businessHours === 'string') {
-				  try {
-					this.form.businessHours = JSON.parse(res.businessHours);
-				  } catch(e) {
-					this.$set(this.form, 'businessHours', [{ startTime: '', endTime: '' }]);
-				  }
-				} else {
-				  this.$set(this.form, 'businessHours', res.businessHours || [{ startTime: '', endTime: '' }]);
-				}
-				if(!Array.isArray(this.form.businessHours) || this.form.businessHours.length === 0) {
-				    this.$set(this.form, 'businessHours', [{ startTime: '', endTime: '' }]);
-				}
-				this.open = true;
-
-			},
-			xuanzhemap(){
-				this.opmap = true;
-				// 重置地图地址数据
-				this.mapaddress = null;
-			},
-			// 确认地址坐标选择
-			dituqiueing(){
-				console.log('当前地图地址数据:', this.mapaddress);
-				if(this.mapaddress==null || !this.mapaddress.address || this.mapaddress.address === '地址获取失败'){
-					this.$message.error(this.$t('mendian.Selectmapobtainaddress'));
-					return
-				}
-				this.form.address = this.mapaddress.address;
-				var lat = this.mapaddress.lat.split(",");
-				this.form.latitude = lat[0];
-				this.form.longitude = lat[1];
-				console.log('设置坐标:', this.form.latitude, this.form.longitude);
-				this.opmap = false;
-			},
-			guanbimay(){
-				this.mapaddress =null;
-				this.opmap = false;
-			},
-			reset() {
-				this.form = {
-					image: null,
-					posName: null,
-					posPrice:null,
-					area:'',
-					address:null,
-					longitude:null,
-					latitude:null,
-					briefIntroduction:null,
-					type:0, // 设置默认门店类型为餐厅
-					isNightMarket:0,
-					nightMarketId:null,
-					hygienePermit:null,
-					openBusiness:null,
-					windingUp:null,
-					sort:[],
-					userId:this.user.userId,
-					state:0,
-					serverType:null,
-					telephone:null,
-					logo:null,
-					businessHours: [{ startTime: '', endTime: '' }]
-				};
-			},
-			handleAdd(){
-				this.reset();
-				this.text = this.$t('mendian.AddStore');
-				this.checkList = [];
-				// 设置默认门店类型为餐厅(0)
-				this.form.type = 0;
-				this.open = true;
-				// 根据默认门店类型获取对应的分类
-				this.getfenleilistByTag();
-			},
-			cancel() {
-			  this.open = false;
-			  this.checkList = [];
-			  this.reset();
-			},
-			getpinguilist(){
-				var that = this;
-				that.loding = true;
-				storelistlist(this.queryParams).then(response => {
-					that.loding = false;
-					this.total = response.data.total;
-					this.tableData = response.data.records;
-					// console.log("获取门店列表",response);
-				});
-			},
-			getfenlei(){
-				getfenlei().then(res=>{
-					console.log('获取分类',res);
-					this.fenlei = res.rows;
-				})
-			},
-             getfenleilistByTag(){
-         if(this.form.type === undefined || this.form.type === null){
-           this.$message.warning("请先选择门店类型");
-           return;
-         }
-         let tag = this.form.type === 0 ? "food" : "mall";
-         console.log('正在获取分类,门店类型:', this.form.type, '标签:', tag);
-         getfenleilistByTag(tag).then(res=>{
-           console.log('获取分类成功:', res);
-           if (res && res.data) {
-             this.fenlei = res.data;
-             console.log('分类列表已更新:', this.fenlei);
-           } else {
-             this.fenlei = [];
-             console.log('分类数据为空或格式不正确');
-           }
-         }).catch(error => {
-           console.error('获取分类失败:', error);
-           this.$message.error('获取分类失败,请重试');
-           this.fenlei = [];
-         })
-       },
-      handleTypeChange(){
-        // 清空已选择的分类
-        this.form.sort = [];
-        // 根据门店类型获取对应的分类
-        this.getfenleilistByTag();
-      },
-      handleSortChange(){
-        console.log('分类选择变化:', this.form.sort);
-      },
-                     // 调试方法:检查分类数据状态
-        debugCategoryData(){
-          console.log('=== 分类数据调试信息 ===');
-          console.log('门店类型:', this.form.type);
-          console.log('分类列表长度:', this.fenlei ? this.fenlei.length : 0);
-          console.log('分类列表数据:', this.fenlei);
-          console.log('已选择的分类:', this.form.sort);
-          console.log('选中的分类名称:', this.selectedCategoryNames);
-          console.log('分类数据类型:', typeof this.form.sort);
-          console.log('分类数据是否为数组:', Array.isArray(this.form.sort));
-          if (typeof this.form.sort === 'string') {
-            console.log('字符串格式的分类数据:', this.form.sort);
-          }
-          console.log('======================');
-        },
-			getfuleix(){
-				getfwleixing().then(res=>{
-					console.log('获取服务类型',res);
-					this.fwlxlist = res.rows;
-				})
-			},
-			getNightMarketList(){
-				getNightMarketlist().then(res=>{
-					console.log('获取夜市列表',res);
-					this.nightMarketList = res.data || [];
-				})
-			},
-			//翻页
-			handleSizeChange(val) {
-				// console.log(`每页 ${val} 条`);
-				this.queryParams.size = val;
-				this.getpinguilist();
-			},
-			handleCurrentChange(val) {
-				// console.log(`当前页: ${val}`);
-				this.queryParams.page = val;
-				this.getpinguilist();
-			},
-			handleAvatarlogo(res, file) {
-				// this.upimg = URL.createObjectURL(file.raw);
-				this.form.logo = file.response.data;
-				// console.log('上传图片',file.response);
-
-			},
-			handleAvatarSuccess(res, file) {
-				// this.upimg = URL.createObjectURL(file.raw);
-				this.form.image = file.response.data;
-				// console.log('上传图片',file.response);
-
-			},
-			beforeAvatarUpload(file) {
-				const isJPG = file.type === 'image/jpeg';
-				const isLt2M = file.size / 1024 / 1024 < 2;
-
-				if (!isJPG) {
-				  this.$message.error(this.$t('mendian.ItcanonlyJPG'));
-				}
-				if (!isLt2M) {
-				  this.$message.error(this.$t('mendian.Cannotexceed'));
-				}
-				return isJPG && isLt2M;
-			},
-			addBusinessHour() {
-			  this.form.businessHours.push({ startTime: '', endTime: '' });
-			},
-			removeBusinessHour(idx) {
-			  this.form.businessHours.splice(idx, 1);
-			},
-		}
-	}
-</script>
-
-<style>
-	.avatar-uploader .el-upload {
-	    border: 1px dashed #d9d9d9;
-	    border-radius: 6px;
-	    cursor: pointer;
-	    position: relative;
-	    overflow: hidden;
-	  }
-	  .avatar-uploader .el-upload:hover {
-	    border-color: #409EFF;
-	  }
-	  .avatar-uploader-icon {
-	    font-size: 28px;
-	    color: #8c939d;
-	    width: 100px;
-	    height: 100px;
-	    line-height: 100px;
-	    text-align: center;
-	  }
-	  .avatar {
-	    width: 100px;
-	    height: 100px;
-	    display: block;
-	  }
-</style>

+ 0 - 208
foodie_sj_vue/src/views/AcidrollingPlan.vue

@@ -1,208 +0,0 @@
-<template>
-	<div>
-		<el-breadcrumb separator="/">
-		  <el-breadcrumb-item :to="{ path: '/' }">{{$t('fenlei.home')}}</el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('fenlei.Management')}}</a></el-breadcrumb-item>
-		  <el-breadcrumb-item>{{$t('fenlei.CATEGORY')}}</el-breadcrumb-item>
-		</el-breadcrumb>
-		<div style="margin-top: 30px;display: flex;align-items: center;">
-			<el-button v-for="item in mdlist" :type="dqmd==item.id?'primary':'info'" class="biaoqian" @click="xuanzhemd(item.id)">{{item.posName}}</el-button>
-		</div>
-		<el-row :gutter="10" style="margin-top: 20px;margin-bottom: 20px;">
-		  <el-col :span="1.5">
-		    <el-button
-		      type="primary"
-		      plain
-		      icon="el-icon-plus"
-		      size="mini"
-		      @click="handleAdd"
-		    >{{$t('fenlei.Addcategory')}}</el-button>
-		  </el-col>
-		</el-row>
-		<el-table ref="filterTable" v-loading="loding"  :data="tableData" :header-cell-style="{background:'#f0f0f0'}">
-			<el-table-column
-				prop="sort"
-				label="id"
-			>
-			</el-table-column>
-			<el-table-column
-				prop="name"
-				:label="$t('fenlei.Classiname')"
-			>
-			</el-table-column>
-			<el-table-column
-				fixed="right"
-				:label="$t('fenlei.operate')"
-				width="150">
-				<template slot-scope="scope">
-					<el-button @click="handleClick(scope.row)" type="text" size="small">{{$t('fenlei.modify')}}</el-button>
-					<el-button @click="delechansu(scope.row)" type="text" size="small">{{$t('fenlei.delete')}}</el-button>
-				</template>
-			</el-table-column>
-		</el-table>
-		<el-dialog :title="text" :visible.sync="open" :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'490px':'400px'" append-to-body>
-			<el-form ref="form" :model="form" :rules="rules" :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'170px':'80px'">
-				<el-form-item :label="$t('fenlei.id')" prop="sort">
-					<el-input v-model="form.sort" :placeholder="$t('fenlei.sodi')" />
-				</el-form-item>
-				<el-form-item :label="$t('fenlei.Classiname')" prop="name">
-					<el-input v-model="form.name" :placeholder="$t('fenlei.Plearname')" />
-				</el-form-item>
-			</el-form>
-			<div slot="footer" class="dialog-footer">
-				<el-button type="primary" @click="dituqiueing">{{$t('fenlei.determine')}}</el-button>
-				<el-button @click="cancel">{{$t('fenlei.cancellation')}}</el-button>
-			</div>
-		</el-dialog>
-	</div>
-</template>
-
-<script>
-	import {getordfenlei,storelistlist,addfenlei,delefenle} from '@/api/fenlei';
-	import Bus from '../utils/Bus.js'
-	export default{
-		name:"AcidrollingCapacity",
-		data(){
-			return {
-				seruer: process.env.VUE_APP_BASE_URL ,
-				loding:false,
-				dqmd:0,
-				tableData:[],
-				mdlist:[],
-				text:'',
-				open:false,
-				form:{},
-				language:this.$t('loding.lass'),
-				// 表单校验
-				rules: {
-				  name: [
-				    { required: true, message:this.$t('fenlei.Classifyempty'), trigger: "blur" }
-				  ],
-				},
-			}
-		},
-		created() {
-			var that = this;
-			that.getstorelist();
-			Bus.$on('l18zh',function(res){
-				that.language = res;
-				that.dqmd = that.dqmd==0?0:that.dqmd;
-				that.getlenlei(that.dqmd);
-			})
-		},
-		methods:{
-			reset() {
-				this.form = {
-					mendid: null,
-					name: null,
-					img:null,
-					sort:null,
-					language:null
-				};
-			},
-			getstorelist(){
-				storelistlist().then(res=>{
-					// console.log('门店列表',res)
-					this.dqmd = this.dqmd==0?res.data.records[0].id:this.dqmd;
-					this.mdlist = res.data.records;
-					this.getlenlei(this.dqmd);
-				})
-			},
-			//选择门店
-			xuanzhemd(id){
-				this.dqmd = id;
-				this.getlenlei(id);
-			},
-			getlenlei(id){
-				var lang = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-				getordfenlei(id,lang).then(res=>{
-					console.log('分类',res)
-					this.tableData = res.data;
-				})
-			},
-			//添加分类
-			handleAdd(){
-				this.text = this.$t('fenlei.Addcategory');
-				this.reset();
-				this.form.mendid = this.dqmd;
-				this.form.language = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-				this.open = true;
-			},
-			//提交分类
-			dituqiueing(){
-				this.$refs["form"].validate(valid => {
-				  if (valid) {
-					addfenlei(this.form).then(res=>{
-						// console.log('提交分类',res);
-						if(res.code==200){
-							this.getlenlei(this.dqmd);
-							this.cancel();
-							this.$message({
-								type: 'success',
-								message: this.$t('fenlei.successfully')
-							});
-						}else{
-							this.$message({
-								type: 'info',
-								message: this.$t('fenlei.Deletefailed')
-							});
-						}
-
-					})
-				  }
-				});
-			},
-			cancel() {
-			  this.open = false;
-			  this.reset();
-			},
-			//修改分类
-			handleClick(res){
-				this.text = this.$t('fenlei.Modifyclass');
-				this.form = res;
-				this.open = true;
-			},
-			//删除分类
-			delechansu(e){
-				this.$confirm(this.$t('fenlei.DeleteCategory'), this.$t('fenlei.prompt'), {
-					confirmButtonText: this.$t('fenlei.determine'),
-					cancelButtonText: this.$t('fenlei.cancellation'),
-					type: 'warning'
-				}).then(() => {
-					delefenle(e.id).then(res=>{
-						// console.log('删除',res);
-						if(res.code==200){
-							this.getlenlei(this.dqmd);
-							this.$message({
-								type: 'success',
-								message: this.$t('fenlei.successful')
-							});
-						}else{
-							this.$message({
-								type: 'info',
-								message: this.$t('fenlei.Deletefailed')
-							});
-						}
-
-					})
-				}).catch(() => {
-					this.$message({
-						type: 'info',
-						message: this.$t('fenlei.undelete')
-					});
-				});
-			}
-		}
-	}
-</script>
-
-<style>
-	.biaoqian{
-		width: 180px;
-		height: 30px;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		margin-right: 10px;
-	}
-</style>

+ 0 - 46
foodie_sj_vue/src/views/Manage.vue

@@ -1,46 +0,0 @@
-<template>
-  <div style="height: 100%;">
-	<el-container style="height:100%; border: 1px solid #eee">
-		<!-- 左边 -->
-	  <el-aside width="220px" style="height: 100%;">
-	    <Aside></Aside>
-	  </el-aside>
-	  
-	  <el-container>
-		  <!-- 顶部 -->
-	    <el-header style="text-align: center;">
-			<Header></Header>
-	    </el-header>
-	    
-		<!-- 主体 -->
-	    <el-main>
-	      <router-view/>
-	    </el-main>
-	  </el-container>
-	</el-container>
-  </div>
-</template>
-
-<script>
-import Aside from "@/components/Aside.vue";
-import Header from "@/components/Header.vue";
- export default {
-	 components:{
-		 Aside,Header
-	},
-     data() {
-     }
-	 
-   };
-</script>
-<style>
-  .el-header {
-    background-color: #B3C0D1;
-    color: #333;
-    line-height: 60px;
-  }
-  
-  .el-aside {
-    color: #333;
-  }
-</style>

+ 0 - 455
foodie_sj_vue/src/views/Promotion.vue

@@ -1,455 +0,0 @@
-<template>
-  <div>
-    <el-breadcrumb separator="/">
-      <el-breadcrumb-item :to="{ path: '/' }">{{$t('cuxiao.home')}}</el-breadcrumb-item>
-      <el-breadcrumb-item>{{$t('cuxiao.yuiquangl')}}</el-breadcrumb-item>
-      <el-breadcrumb-item>{{$t('cuxiao.zxhd')}}</el-breadcrumb-item>
-    </el-breadcrumb>
-    <div style="margin-top: 30px;display: flex;align-items: center;">
-      <el-button v-for="item in storeList" :type="dqmd==item.id?'primary':'info'" class="biaoqian" @click="xuanzhemd(item.id)">{{item.posName}}</el-button>
-    </div>
-    <el-row :gutter="10" style="margin-top: 20px;margin-bottom: 20px;">
-      <el-col :span="1.5">
-        <el-button
-            type="primary"
-            plain
-            icon="el-icon-plus"
-            size="mini"
-            @click="handleAdd"
-        >{{$t('cuxiao.AddCX')}}</el-button>
-      </el-col>
-    </el-row>
-    <el-table ref="filterTable" v-loading="loding"  :data="tableData" :header-cell-style="{background:'#f0f0f0'}">
-      <el-table-column
-          prop="id"
-          label="id"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="salesName"
-          :label="$t('cuxiao.hdmc')"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="salesType"
-          :label="$t('cuxiao.qmfs')"
-          width="200"
-      >
-        <template slot-scope="scope">
-          <span v-if="scope.row.salesType == '1'">{{$t('cuxiao.qmyf')}}</span>
-          <span v-else-if="scope.row.salesType == '2'">{{$t('cuxiao.ddjdz')}}</span>
-          <span v-else-if="scope.row.salesType == '3'">{{$t('cuxiao.ddjdk')}}</span>
-          <span v-else>-</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-          prop="endTime"
-          :label="$t('cuxiao.jsrq')"
-          width="200"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="salesState"
-          :label="$t('cuxiao.hdzt')"
-      >
-        <template slot-scope="scope">
-          <span v-if="scope.row.salesState == '0'">{{$t('cuxiao.salesStateKq')}}</span>
-          <span v-else-if="scope.row.salesState == '1'">{{$t('cuxiao.salesStateTy')}}</span>
-          <span v-else>-</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-          fixed="right"
-          :label="$t('mendian.operate')"
-          width="120">
-        <template slot-scope="scope">
-          <el-button @click="handleUpdate(scope.row)" type="text" size="small">{{$t('cuxiao.modify')}}</el-button>
-          <el-button @click="delechansu(scope.row)" type="text" size="small">{{$t('cuxiao.delete')}}</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div style="width: 100%;display: flex;justify-content: flex-end;">
-      <el-pagination
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          :current-page="queryParams.page"
-          :page-size="queryParams.size"
-          layout="total, prev, pager, next"
-          :total="total">
-      </el-pagination>
-    </div>
-    <!-- 添加或修改门店分类对话框 -->
-    <el-dialog :title="text" :visible.sync="open" :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'650px':'600px'" append-to-body>
-      <el-alert
-          v-if="!form.edit"
-          :title="$t('cuxiao.bnxg')"
-          type="error"
-          show-icon
-          :closable="false"
-          style="margin-bottom: 16px;"
-      />
-      <el-form ref="form" :model="form" :rules="rules" :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'180px':'100px'">
-        <el-form-item :label="$t('quanyi.md')">
-          <el-select :disabled="!form.edit" v-model="form.shId" :placeholder="$t('quanyi.xcmd')" style="width: 180px;" >
-            <el-option v-for="item in storeList" :key="item.id" :label="item.posName" :value="item.id" />
-          </el-select>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.hdmc')" prop="salesName">
-          <el-input v-model="form.salesName" :placeholder="$t('cuxiao.hdmcms')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.hdhb')" prop="poster">
-          <el-upload
-              class="avatar-uploader"
-              :action="seruer+'/utils/Upload'"
-              :show-file-list="false"
-              :on-success="handleAvatarlogo"
-              :before-upload="beforeAvatarUpload">
-            <img v-if="form.poster" :src="seruer+form.poster" class="avatar">
-            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-          </el-upload>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.qmfs')" prop="salesType">
-          <el-radio :disabled="!form.edit" v-model="form.salesType" label="1">{{$t('cuxiao.qmyf')}}</el-radio>
-          <el-radio :disabled="!form.edit" v-model="form.salesType" label="2">{{$t('cuxiao.ddjdz')}}</el-radio>
-          <el-radio :disabled="!form.edit" v-model="form.salesType" label="3">{{$t('cuxiao.ddjdk')}}</el-radio>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.qmz')" prop="salesReduction">
-          <el-input type="number" v-model="form.salesReduction" :placeholder="$t('cuxiao.qmzsm')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.sytj')" prop="salesCondition">
-          <el-input type="number" v-model="form.salesCondition" :placeholder="$t('cuxiao.sytjsm')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.salesFund')" prop="salesFund">
-          <el-input type="number" v-model="form.salesFund" :placeholder="$t('cuxiao.salesFundsm')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.endTime')" prop="endTime">
-<!--          <el-input v-model="form.endTime" :placeholder="$t('cuxiao.endTimesm')" />-->
-          <el-date-picker clearable
-                          v-model="form.endTime"
-                          type="date"
-                          value-format="yyyy-MM-dd"
-                          :placeholder="$t('cuxiao.endTimesm')" :readonly="!form.edit">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.salesState')" prop="salesState">
-          <el-radio v-model="form.salesState" label="0">{{$t('cuxiao.salesStateKq')}}</el-radio>
-          <el-radio v-model="form.salesState" label="1">{{$t('cuxiao.salesStateTy')}}</el-radio>
-        </el-form-item>
-        <el-form-item :label="$t('cuxiao.illustrate')" prop="illustrate">
-          <el-input v-model="form.illustrate" type="textarea" :placeholder="$t('cuxiao.illustrate')" />
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="tijiaobaocun">{{$t('mendian.determine')}}</el-button>
-        <el-button @click="cancel">{{$t('mendian.cancellation')}}</el-button>
-      </div>
-    </el-dialog>
-
-  </div>
-</template>
-
-<script>
-import {storelistlist,getordfenlei,getidlist,setposfood,delefood} from '@/api/food';
-import {getshSalesPromotion, listshSalesPromotion,addshSalesPromotion,updateshSalesPromotion,delshSalesPromotion} from '@/api/promotion'
-import googmap from "@/components/googmap.vue";
-import Bus from "@/utils/Bus";
-export default{
-  name:"AcidrollingCapacity",
-  components:{
-    googmap
-  },
-  data(){
-    return {
-      seruer: process.env.VUE_APP_BASE_URL ,
-      loding:false,
-      tableData:[],
-      total:0,
-      checkList:[],
-      //分页
-      queryParams: {
-        page: 1,
-        size: 10,
-        language:null,
-        shId:null,
-      },
-      storeList: [], // 门店列表
-      selectedStoreId: '', // 当前选中的门店ID
-      fenlei:[],
-      fwlxlist:[],
-      open:false,
-      opmap:false,
-      form:{edit:true},
-      user:{},
-      mdid:'',
-      // 表单校验
-      rules: {
-        salesName: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value) {
-                callback(new Error(this.$t('cuxiao.hdmcEpty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        salesType: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value) {
-                callback(new Error(this.$t('cuxiao.qmfsEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        endTime: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value) {
-                callback(new Error(this.$t('cuxiao.endTimeEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        salesState: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('cuxiao.salesStateEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        salesReduction:[
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('cuxiao.salesReductionEmty')));
-              } else if (this.form.salesType != 1 && value <= 0) {
-                callback(new Error(this.$t('cuxiao.salesReduction0')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-      },
-      mapaddress:null,
-      text:'',
-      dqmd:null,
-      language:this.$t('loding.lass'),
-    }
-  },
-  created() {
-    this.getStoreList();
-    Bus.$on('l18zh', (res) => {
-      this.language = res;
-    });
-  },
-  watch: {
-    language(newVal) {
-      // 语言变化时执行逻辑
-      this.listshSalesPromotion();
-    }
-  },
-  methods:{
-    xuanzhemd(id){
-      this.dqmd = id;
-      this.listshSalesPromotion()
-    },
-    getStoreList() {
-      storelistlist().then(res => {
-        if (res.data && res.data.records && res.data.records.length > 0) {
-          this.storeList = res.data.records;
-          this.selectedStoreId = res.data.records[0].id;
-          this.dqmd=res.data.records[0].id;
-          this.listshSalesPromotion()
-        }
-      });
-    },
-    delechansu(e){
-      this.$confirm(this.$t('cuxiao.delSm'), this.$t('mendian.prompt'), {
-        confirmButtonText: this.$t('mendian.determine'),
-        cancelButtonText: this.$t('mendian.cancellation'),
-        type: 'warning'
-      }).then(() => {
-        delshSalesPromotion(e.id).then(res=>{
-          // console.log('删除',res);
-          if(res.code==200){
-            this.listshSalesPromotion();
-            this.$message({
-              type: 'success',
-              message: this.$t('mendian.successful')
-            });
-          }else{
-            this.$message({
-              type: 'info',
-              message: this.$t('mendian.Deletefailed')
-            });
-          }
-
-        })
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: this.$t('mendian.undelete')
-        });
-      });
-
-    },
-    tijiaobaocun(){
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.id != null) {
-            updateshSalesPromotion(this.form).then(res=>{
-              // console.log('操作成功',res)
-              if(res.code==200){
-                this.listshSalesPromotion();
-                this.open = false;
-                this.reset();
-              }
-            })
-          }else{
-            this.form.language = this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-            addshSalesPromotion(this.form).then(res=>{
-              // console.log('操作成功',res)
-              if(res.code==200){
-                this.listshSalesPromotion();
-                this.open = false;
-                this.reset();
-              }
-            })
-          }
-
-        }
-      });
-
-    },
-
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const id = row.id
-      getshSalesPromotion(id).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.text = this.$t('cuxiao.modify');
-      });
-    },
-
-
-    reset() {
-      this.form = {
-        id: null,
-        salesName: null,
-        salesType: null,
-        salesReduction: null,
-        salesCondition: null,
-        salesFund: null,
-        endTime: null,
-        poster: null,
-        salesState: null,
-        illustrate: null,
-        shId:null,
-        edit:true
-      };
-    },
-    handleAdd(){
-      this.reset();
-      this.text = this.$t('cuxiao.AddCX');
-      this.open = true;
-      this.form.shId=this.dqmd
-    },
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    listshSalesPromotion(){
-      var that = this;
-      that.loding = true;
-      this.queryParams.shId=this.dqmd
-      const language =this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-      this.queryParams.language=language
-      listshSalesPromotion(this.queryParams).then(response => {
-        that.loding = false;
-        this.total = response.data.total;
-        this.tableData = response.data.records;
-
-      });
-    },
-
-    //翻页
-    handleSizeChange(val) {
-      // console.log(`每页 ${val} 条`);
-      this.queryParams.size = val;
-      this.listshSalesPromotion();
-    },
-    handleCurrentChange(val) {
-      // console.log(`当前页: ${val}`);
-      this.queryParams.page = val;
-      this.getpinguilist();
-    },
-    handleAvatarlogo(res, file) {
-      // this.upimg = URL.createObjectURL(file.raw);
-      this.form.poster = file.response.data;
-      // console.log('上传图片',file.response);
-
-    },
-    beforeAvatarUpload(file) {
-      const isJPG = file.type === 'image/jpeg';
-      const isLt2M = file.size / 1024 / 1024 < 2;
-
-      if (!isJPG) {
-        this.$message.error(this.$t('cuxiao.ItcanonlyJPG'));
-      }
-      if (!isLt2M) {
-        this.$message.error(this.$t('cuxiao.Cannotexceed'));
-      }
-      return isJPG && isLt2M;
-    }
-  }
-}
-</script>
-
-<style>
-.avatar-uploader .el-upload {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-}
-.avatar-uploader .el-upload:hover {
-  border-color: #409EFF;
-}
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 100px;
-  height: 100px;
-  line-height: 100px;
-  text-align: center;
-}
-.avatar {
-  width: 100px;
-  height: 100px;
-  display: block;
-}
-</style>

+ 0 - 661
foodie_sj_vue/src/views/Quanyi.vue

@@ -1,661 +0,0 @@
-<template>
-  <div>
-    <el-breadcrumb separator="/">
-      <el-breadcrumb-item :to="{ path: '/' }">{{ $t('cuxiao.home') }}</el-breadcrumb-item>
-      <el-breadcrumb-item>{{ $t('cuxiao.yuiquangl') }}</el-breadcrumb-item>
-      <el-breadcrumb-item>{{ $t('quanyi.kyyhq') }}</el-breadcrumb-item>
-    </el-breadcrumb>
-    <div style="margin-top: 30px;display: flex;align-items: center;">
-      <el-button v-for="item in storeList" :type="dqmd==item.id?'primary':'info'" class="biaoqian" @click="xuanzhemd(item.id)">{{item.posName}}</el-button>
-    </div>
-    <el-row :gutter="10" style="margin-top: 20px;margin-bottom: 20px;">
-      <el-col :span="1.5">
-        <el-button
-            type="primary"
-            plain
-            icon="el-icon-plus"
-            size="mini"
-            @click="handleAdd"
-        >{{ $t('quanyi.add') }}
-        </el-button>
-      </el-col>
-    </el-row>
-    <el-table ref="filterTable" v-loading="loding" :data="tableData" :header-cell-style="{background:'#f0f0f0'}">
-      <el-table-column
-          prop="id"
-          label="id"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="name"
-          :label="$t('quanyi.yhmc')"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="yhfangs"
-          :label="$t('quanyi.yhfs')"
-          width="200"
-      >
-        <template slot-scope="scope">
-          <span v-if="scope.row.yhfangs== '1'">{{ $t('quanyi.yhqlx1') }}</span>
-          <span v-else-if="scope.row.yhfangs == '2'">{{ $t('quanyi.yhqlx2') }}</span>
-          <span v-else-if="scope.row.yhfangs == '3'">{{ $t('quanyi.yhqlx3') }}</span>
-<!--          <span v-else-if="scope.row.yhfangs == '3'">{{ $t('quanyi.yhqlx4') }}</span>-->
-          <span v-else>-</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-          prop="total"
-          :label="$t('quanyi.total')"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="claimedCount"
-          :label="$t('quanyi.claimedCount')"
-      >
-      </el-table-column>
-
-      <el-table-column
-          prop="createTime"
-          :label="$t('quanyi.creatTime')"
-          width="200"
-      >
-      </el-table-column>
-      <el-table-column
-          prop="state"
-          :label="$t('quanyi.zt')"
-      >
-        <template slot-scope="scope">
-          <span v-if="scope.row.state == '0'">{{ $t('quanyi.qy') }}</span>
-          <span v-else-if="scope.row.state == '1'">{{ $t('quanyi.gb') }}</span>
-          <span v-else>-</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-          fixed="right"
-          :label="$t('mendian.operate')"
-          width="120">
-        <template slot-scope="scope">
-          <el-button @click="handleUpdate(scope.row)" type="text" size="small">{{ $t('cuxiao.modify') }}</el-button>
-          <el-button @click="delechansu(scope.row)" type="text" size="small">{{ $t('cuxiao.delete') }}</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div style="width: 100%;display: flex;justify-content: flex-end;">
-      <el-pagination
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          :current-page="queryParams.page"
-          :page-size="queryParams.size"
-          layout="total, prev, pager, next"
-          :total="total">
-      </el-pagination>
-    </div>
-    <!-- 添加或修改对话框 -->
-    <el-dialog :title="text" :visible.sync="open"
-               :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'650px':'600px'" append-to-body>
-      <el-alert
-          v-if="!form.edit"
-          :title="$t('quanyi.bnxg')"
-          type="error"
-          show-icon
-          :closable="false"
-          style="margin-bottom: 16px;"
-      />
-      <el-form ref="form" :model="form" :rules="rules"
-               :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'180px':'100px'">
-          <el-form-item :label="$t('quanyi.md')">
-            <el-select :disabled="!form.edit" v-model="form.shId" :placeholder="$t('quanyi.xcmd')" style="width: 180px;" @change="handleStoreChange">
-              <el-option v-for="item in storeList" :key="item.id" :label="item.posName" :value="item.id" />
-            </el-select>
-          </el-form-item>
-        <el-form-item :label="$t('quanyi.yhmc')" prop="name">
-          <el-input v-model="form.name" :placeholder="$t('quanyi.sryhmc')" :readonly="!form.edit"/>
-        </el-form-item>
-<!--        <el-form-item :label="$t('cuxiao.hdhb')" prop="poster">-->
-<!--          <el-upload-->
-<!--              class="avatar-uploader"-->
-<!--              :action="seruer+'/utils/Upload'"-->
-<!--              :show-file-list="false"-->
-<!--              :on-success="handleAvatarlogo"-->
-<!--              :before-upload="beforeAvatarUpload">-->
-<!--            <img v-if="form.poster" :src="seruer+form.poster" class="avatar">-->
-<!--            <i v-else class="el-icon-plus avatar-uploader-icon"></i>-->
-<!--          </el-upload>-->
-<!--        </el-form-item>-->
-        <el-form-item :label="$t('quanyi.yhfs')" prop="yhfangs" >
-          <el-radio :disabled="!form.edit" v-model="form.yhfangs" :label="1">{{ $t('quanyi.yhqlx1') }}</el-radio>
-          <el-radio :disabled="!form.edit" v-model="form.yhfangs" :label="2">{{ $t('quanyi.yhqlx2') }}</el-radio>
-          <el-radio :disabled="!form.edit" v-model="form.yhfangs" :label="3">{{ $t('quanyi.yhqlx3') }}</el-radio>
-<!--          <el-radio v-model="form.yhfangs" :label="3">{{ $t('quanyi.yhqlx4') }}</el-radio>-->
-        </el-form-item>
-<!--        <el-form-item v-if="form.yhfangs == '3'" :label="$t('quanyi.xcsp')" prop="spId">-->
-<!--          <div style="display: flex; align-items: center;">-->
-<!--            <el-button type="primary" @click="openSelectProductDialog">{{$t('quanyi.xcsp')}}</el-button>-->
-<!--            <div v-if="selectedProduct && selectedProduct.name" style="margin-left: 16px;display: flex;align-items: center;">-->
-<!--              <img v-if="selectedProduct.image" :src="seruer+selectedProduct.image" style="width:40px;height:40px;margin-right:8px;" />-->
-<!--              <span>{{selectedProduct.name}}</span>-->
-<!--            </div>-->
-<!--          </div>-->
-<!--        </el-form-item>-->
-        <el-form-item :label="$t('quanyi.yhnum')" prop="yhnum">
-          <el-input type="number" v-model="form.yhnum" :placeholder="$t('quanyi.sryhnum')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('quanyi.total')" prop="total">
-          <el-input type="number" v-model="form.total" :placeholder="$t('quanyi.srtotal')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('quanyi.lqxz')" prop="lqxz">
-          <el-input type="number" v-model="form.lqxz" :placeholder="$t('quanyi.srlqxz')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('quanyi.validity')" prop="validity">
-          <el-input type="number" v-model="form.validity"  min="1" :placeholder="$t('quanyi.srvalidity')" :readonly="!form.edit"/>
-        </el-form-item>
-
-        <el-form-item :label="$t('quanyi.tiaojian')" prop="tiaojian">
-          <el-input type="number" v-model="form.tiaojian" :placeholder="$t('quanyi.srtiaojian')" :readonly="!form.edit"/>
-        </el-form-item>
-        <el-form-item :label="$t('quanyi.zt')" prop="state">
-          <el-radio v-model="form.state" label="0">{{ $t('quanyi.qy') }}</el-radio>
-          <el-radio v-model="form.state" label="1">{{ $t('quanyi.gb') }}</el-radio>
-        </el-form-item>
-        <el-form-item :label="$t('quanyi.shuoming')" prop="shuoming">
-          <el-input type="textarea" v-model="form.shuoming" :placeholder="$t('quanyi.srshuoming')"/>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="tijiaobaocun">{{ $t('mendian.determine') }}</el-button>
-        <el-button @click="cancel">{{ $t('mendian.cancellation') }}</el-button>
-      </div>
-    </el-dialog>
-    <el-dialog :title="$t('quanyi.xcsp')" :visible.sync="selectProductDialogVisible" width="800px">
-      <div style="margin-bottom: 12px;">
-        <el-form inline>
-<!--          <el-form-item :label="$t('quanyi.md')">-->
-<!--            <el-select v-model="selectedStoreId" :placeholder="$t('quanyi.xcmd')" style="width: 180px;" @change="handleStoreChange">-->
-<!--              <el-option v-for="item in storeList" :key="item.id" :label="item.posName" :value="item.id" />-->
-<!--            </el-select>-->
-<!--          </el-form-item>-->
-          <el-form-item :label="$t('quanyi.spfl')">
-            <el-select v-model="selectedProductCategory" :placeholder="$t('quanyi.spfl')" style="width: 180px;" @change="handleCategoryChange">
-              <el-option v-for="item in productCategoryList" :key="item.id" :label="item.name" :value="item.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item :label="$t('quanyi.spmc')">
-            <el-input v-model="productTableQuery.name" :placeholder="$t('quanyi.spmc')" style="width: 180px;" @keyup.enter.native="getProductTableData" />
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" icon="el-icon-search" @click="getProductTableData">{{$t('quanyi.cx')}}</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-      <el-table :data="productTableData" highlight-current-row @current-change="handleProductTableSelect" :row-key="row=>row.id" style="width:100%;">
-        <el-table-column type="index" label="#" width="50" />
-        <el-table-column prop="name" :label="$t('quanyi.spmc')" />
-        <el-table-column prop="image" :label="$t('quanyi.tp')" width="80">
-          <template slot-scope="scope">
-            <img v-if="scope.row.image" :src="seruer+scope.row.image" style="width:40px;height:40px;" />
-          </template>
-        </el-table-column>
-        <el-table-column prop="price" :label="$t('quanyi.jg')" />
-      </el-table>
-      <div style="margin-top: 10px;text-align: right;">
-        <el-pagination
-          @size-change="handleProductTableSizeChange"
-          @current-change="handleProductTableCurrentChange"
-          :current-page="productTableQuery.page"
-          :page-size="productTableQuery.size"
-          layout="total, prev, pager, next"
-          :total="productTableTotal">
-        </el-pagination>
-      </div>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="selectProductDialogVisible=false">{{$t('quanyi.qx')}}</el-button>
-        <el-button type="primary" @click="handleProductSelectConfirm">{{$t('quanyi.qd')}}</el-button>
-      </span>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import {listQuanyi,getQuanyi,addQuanyi,updateQuanyi,delQuanyi} from '@/api/quanyi';
-import googmap from "@/components/googmap.vue";
-import { storelistlist, getordfenlei,getFoodPageList,getFood } from '@/api/food';
-import Bus from "@/utils/Bus"; // 路径按你实际情况
-
-export default {
-  name: "AcidrollingCapacity",
-  components: {
-    googmap
-  },
-  data() {
-    return {
-      seruer: process.env.VUE_APP_BASE_URL ,
-      loding: false,
-      tableData: [],
-      total: 0,
-      checkList: [],
-      //分页
-      queryParams: {
-        page: 1,
-        size: 10,
-        language:this.$t('loding.lass')
-      },
-      fenlei: [],
-      fwlxlist: [],
-      open: false,
-      opmap: false,
-      form: {edit:true},
-      user: {},
-      mdid: '',
-      // 表单校验
-      rules: {
-        name: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value) {
-                callback(new Error(this.$t('quanyi.nameEpty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        yhfangs: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.yhfangsEmpty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'change'
-          }
-        ],
-        yhnum: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.yhnumEmty')));
-              } else if (this.form.yhfangs != 1 && value <= 0) {
-                callback(new Error(this.$t('quanyi.yhmnum0')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        total: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.totalEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        lqxz: [
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.lqxzEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        validity:[
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.validityEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'blur'
-          }
-        ],
-        state:[
-          {
-            required: true,
-            validator: (rule, value, callback) => {
-              if (!value && value !== 0) {
-                callback(new Error(this.$t('quanyi.stateEmty')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'change'
-          }
-        ],
-        spId: [
-          {
-            validator: (rule, value, callback) => {
-              if (this.form.yhfangs == '3' && !value) {
-                callback(new Error(this.$t('quanyi.qxcsp')));
-              } else {
-                callback();
-              }
-            },
-            trigger: 'change'
-          }
-        ]
-      },
-      mapaddress: null,
-      text: '',
-      productList: [],
-      selectProductDialogVisible: false,
-      productTableData: [],
-      productTableTotal: 0,
-      productTableQuery: { page: 1, size: 8, name: '', type: '' },
-      selectedProduct: {},
-
-      storeList: [], // 门店列表
-      selectedStoreId: '', // 当前选中的门店ID
-      productCategoryList: [], // 分类列表
-      selectedProductCategory: '', // 当前选中的分类ID
-      language:this.$t('loding.lass'),
-      dqmd:null,
-    }
-  },
-  created() {
-    this.getStoreList();
-    const that = this;
-    Bus.$on('l18zh',function(res){
-      that.language = res;
-    })
-  },
-  watch: {
-    language(newVal) {
-      // 语言变化时执行逻辑
-      this.listQuanyi();
-    }
-  },
-  methods: {
-    xuanzhemd(id){
-      this.dqmd = id;
-      this.listQuanyi()
-    },
-    delechansu(e) {
-      this.$confirm(this.$t('cuxiao.delSm'), this.$t('mendian.prompt'), {
-        confirmButtonText: this.$t('mendian.determine'),
-        cancelButtonText: this.$t('mendian.cancellation'),
-        type: 'warning'
-      }).then(() => {
-        delQuanyi(e.id).then(res => {
-          // console.log('删除',res);
-          if (res.code == 200) {
-            this.listQuanyi();
-            this.$message({
-              type: 'success',
-              message: this.$t('mendian.successful')
-            });
-          } else {
-            this.$message({
-              type: 'info',
-              message: this.$t('mendian.Deletefailed')
-            });
-          }
-
-        })
-      }).catch(() => {
-        this.$message({
-          type: 'info',
-          message: this.$t('mendian.undelete')
-        });
-      });
-
-    },
-    tijiaobaocun() {
-      console.log(this.form)
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if (this.form.id != null) {
-            updateQuanyi(this.form).then(res => {
-              // console.log('操作成功',res)
-              if (res.code == 200) {
-                this.listQuanyi();
-                this.open = false;
-                this.reset();
-              }
-            })
-          } else {
-            this.form.language=this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-            addQuanyi(this.form).then(res => {
-              // console.log('操作成功',res)
-              if (res.code == 200) {
-                this.listQuanyi();
-                this.open = false;
-                this.reset();
-              }
-            })
-          }
-
-        }
-      });
-
-    },
-
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const id = row.id;
-      getQuanyi(id).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.text = this.$t('cuxiao.modify');
-        // 关键:如果是减免个别商品,并且有 spId,查商品详情
-        if(this.form.yhfangs == '3' && this.form.spId) {
-          getFood(this.form.spId).then(f => {
-            this.selectedProduct = {
-              id: f.data.id,
-              name: f.data.name,
-              image: f.data.image
-            };
-          });
-        } else {
-          this.selectedProduct = {};
-        }
-      });
-    },
-    reset() {
-      this.form = {
-        id: null,
-        vip: null,
-        yhfangs: null,
-        yhnum: null,
-        name: null,
-        shuoming: null,
-        tiaojian: null,
-        num: null,
-        state: null,
-        total: null,
-        validity: null,
-        lqxz: null,
-        shId:null,
-        spId: null,
-        poster:null,
-        language:null,
-        edit:true
-      };
-      this.selectedProduct = {};
-    },
-    handleAdd() {
-      this.reset();
-      this.text = this.$t('quanyi.add');
-      this.open = true;
-      this.form.shId=this.dqmd;
-    },
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    listQuanyi() {
-      var that = this;
-      that.loding = true;
-      this.queryParams.language= this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-      this.queryParams.shId= this.dqmd;
-      listQuanyi(this.queryParams).then(response => {
-        that.loding = false;
-        this.total = response.data.total;
-        this.tableData = response.data.records;
-      });
-    },
-
-    //翻页
-    handleSizeChange(val) {
-      // console.log(`每页 ${val} 条`);
-      this.queryParams.size = val;
-      this.listQuanyi();
-    },
-    handleCurrentChange(val) {
-      // console.log(`当前页: ${val}`);
-      this.queryParams.page = val;
-      this.listQuanyi();
-    },
-    handleAvatarlogo(res, file) {
-      // this.upimg = URL.createObjectURL(file.raw);
-      this.form.poster = file.response.data;
-      // console.log('上传图片',file.response);
-
-    },
-
-    beforeAvatarUpload(file) {
-      const isJPG = file.type === 'image/jpeg';
-      const isLt2M = file.size / 1024 / 1024 < 2;
-
-      if (!isJPG) {
-        this.$message.error(this.$t('quanyi.ItcanonlyJPG'));
-      }
-      if (!isLt2M) {
-        this.$message.error(this.$t('quanyi.Cannotexceed'));
-      }
-      return isJPG && isLt2M;
-    },
-
-    openSelectProductDialog() {
-      this.selectProductDialogVisible = true;
-
-    },
-    getStoreList() {
-      storelistlist().then(res => {
-        if (res.data && res.data.records && res.data.records.length > 0) {
-          this.storeList = res.data.records;
-          this.selectedStoreId = res.data.records[0].id;
-          this.dqmd=res.data.records[0].id;
-          this.listQuanyi()
-          this.getProductCategoryList(); // 获取第一个门店的分类
-        }
-      });
-    },
-    getProductCategoryList() {
-      if (!this.selectedStoreId) {
-        this.productCategoryList = [];
-        this.selectedProductCategory = '';
-        return;
-      }
-      const language =this.language=='zh'?'2':this.language=='tw'?'3':this.language=='en'?'1':'0';
-      getordfenlei(this.selectedStoreId, language).then(res => {
-        if (res.data && res.data.length > 0) {
-          this.productCategoryList = res.data;
-          this.selectedProductCategory = res.data[0].id;
-          this.getProductTableData();
-        } else {
-          this.productCategoryList = [];
-          this.selectedProductCategory = '';
-          this.productTableData = [];
-        }
-      });
-    },
-    handleProductTableCurrentChange(val) {
-      this.productTableQuery.page = val;
-      this.getProductTableData();
-    },
-    handleProductTableSizeChange(val) {
-      this.productTableQuery.size = val;
-      this.getProductTableData();
-    },
-    handleProductTableSelect(row) {
-      this.selectedProduct = row;
-    },
-    handleProductSelectConfirm() {
-      if(this.selectedProduct) {
-        this.form.spId = this.selectedProduct.id;
-        this.selectProductDialogVisible = false;
-      } else {
-        this.$message.warning('请选择商品');
-      }
-    },
-    // 门店切换
-    handleStoreChange() {
-      this.selectedStoreId =this.form.shId
-      this.getProductCategoryList();
-    },
-    // 分类切换
-    handleCategoryChange() {
-      this.getProductTableData();
-    },
-    // 获取商品列表
-    getProductTableData() {
-      const lang = this.$t('loding.language')=='zh'?'2':this.$t('loding.language')=='tw'?'3':this.$t('loding.language')=='en'?'1':'0';
-      const params = {
-        page: this.productTableQuery.page,
-        size: this.productTableQuery.size,
-        name: this.productTableQuery.name,
-        lang: lang,
-        flId: this.selectedProductCategory,
-        mdId: this.selectedStoreId // 如果接口需要门店id
-      };
-      getFoodPageList(params).then(res => {
-        if(res.data && res.data.records) {
-          this.productTableData = res.data.records || [];
-          this.productTableTotal = res.data.total || 0;
-        }
-      });
-    },
-  }
-}
-</script>
-
-<style>
-.avatar-uploader .el-upload {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-}
-
-.avatar-uploader .el-upload:hover {
-  border-color: #409EFF;
-}
-
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 100px;
-  height: 100px;
-  line-height: 100px;
-  text-align: center;
-}
-
-.avatar {
-  width: 100px;
-  height: 100px;
-  display: block;
-}
-</style>

+ 0 - 307
foodie_sj_vue/src/views/Review.vue

@@ -1,307 +0,0 @@
-<template>
-  <div>
-    <el-breadcrumb separator="/">
-      <el-breadcrumb-item :to="{ path: '/' }">{{ $t('cuxiao.home') }}</el-breadcrumb-item>
-      <el-breadcrumb-item>{{ $t('review.ddpl') }}</el-breadcrumb-item>
-    </el-breadcrumb>
-
-    <el-row :gutter="10" style="margin-top: 20px;margin-bottom: 20px;">
-      <el-col :span="1.5">
-<!--        <el-button-->
-<!--            type="primary"-->
-<!--            plain-->
-<!--            size="mini"-->
-<!--            @click="handleAdd"-->
-<!--        >{{ $t('review.ck') }}-->
-<!--        </el-button>-->
-      </el-col>
-    </el-row>
-    <el-table ref="filterTable" v-loading="loding" :data="tableData" :header-cell-style="{background:'#f0f0f0'}">
-<!--        <el-table-column type="selection" width="55" align="center" />-->
-        <el-table-column label="id" align="center" prop="id" />
-        <el-table-column :label="$t('review.ddid')" align="center" prop="ddId" />
-        <el-table-column :label="$t('review.pf')" align="center" prop="score" />
-        <el-table-column :label="$t('review.plsj')" align="center" prop="cretim" width="180">
-        </el-table-column>
-        <el-table-column :label="$t('review.plnr')" align="center" prop="content" />
-        <el-table-column :label="$t('review.yhid')" align="center" prop="userId" />
-        <el-table-column :label="$t('review.sfnm')" align="center" prop="
-anonymous">
-          <template slot-scope="scope">
-            <el-tag v-if="scope.row.anonymous==0">{{$t('review.yes')}}</el-tag>
-            <el-tag v-if="scope.row.anonymous==1">{{$t('review.no')}}</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column :label="$t('review.cz')" align="center" class-name="small-padding fixed-width">
-          <template slot-scope="scope">
-            <el-button
-                size="mini"
-                type="text"
-                @click="handleUpdate(scope.row)"
-            >{{$t('review.ck')}}</el-button>
-            <el-button
-                size="mini"
-                type="text"
-                icon="el-icon-delete"
-                @click="handleDelete(scope.row)"
-            >{{$t('review.sc')}}</el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <div style="width: 100%;display: flex;justify-content: flex-end;">
-      <el-pagination
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          :current-page="queryParams.page"
-          :page-size="queryParams.size"
-          layout="total, prev, pager, next"
-          :total="total">
-      </el-pagination>
-    </div>
-    <!-- 添加或修改对话框 -->
-    <el-dialog :title="text" :visible.sync="open"
-               :width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'650px':'600px'" append-to-body>
-      <el-form ref="form" :model="form"
-               :label-width="$t('loding.language')=='en'||$t('loding.language')=='vi'?'180px':'100px'">
-        <el-form-item :label="$t('review.ddid')" prop="ddId">
-          <el-input v-model="form.ddId"  />
-        </el-form-item>
-        <el-form-item :label="$t('review.pf')" prop="score">
-          <el-input v-model="form.score" readonly  />
-        </el-form-item>
-        <el-form-item :label="$t('review.plsj')" prop="cretim">
-          <el-date-picker clearable
-                          v-model="form.cretim"
-                          type="datetime"
-                          value="yyyy-MM-dd HH:mm:ss"
-          >
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item :label="$t('review.plnr')">
-          <el-input type="textarea" v-model="form.content" rows="10"/>
-        </el-form-item>
-        <el-form-item v-if="form.images" :label="$t('review.pltp')" prop="images">
-          <!-- 使用Flex布局水平排列图片 -->
-          <div class="image-container" v-if="form.images">
-            <!-- 多张图片显示 -->
-            <template v-if="form.images.includes(',')">
-              <div v-for="(img, index) in form.images.split(',')"
-                   :key="index"
-                   class="image-wrapper">
-                <img :src="seruer + img.trim()" class="avatar">
-              </div>
-            </template>
-            <!-- 单张图片显示 -->
-            <template v-else>
-              <div class="image-wrapper">
-                <img :src="seruer + form.images" class="avatar">
-              </div>
-            </template>
-          </div>
-
-          <!-- 无图片时显示上传图标 -->
-          <div v-else class="image-container">
-            <span style="line-height: 100px;">{{ $t('review.none') }}</span>
-          </div>
-        </el-form-item>
-        <el-form-item :label="$t('review.yhid')" prop="userId">
-          <el-input v-model="form.userId"   readonly/>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button @click="cancel">{{ $t('mendian.cancellation') }}</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { listReview, getReview, delReview, addReview, updateReview } from "@/api/review";
-import googmap from "@/components/googmap.vue";
-import Bus from "@/utils/Bus";
-import {delshSalesPromotion} from "@/api/promotion"; // 路径按你实际情况
-export default {
-  name: "Review",
-  components: {
-    googmap
-  },
-  data() {
-    return {
-      seruer: process.env.VUE_APP_BASE_URL,
-      loding: false,
-      tableData: [],
-      total: 0,
-
-      //分页
-      queryParams: {
-        page: 1,
-        size: 10,
-      },
-      open: false,
-      form: {},
-      user: {},
-      text: '',
-      language:this.$t('loding.lass'),
-      dqmd:null,
-    }
-  },
-  created() {
-    const that = this;
-    this.listReview();
-    Bus.$on('l18zh',function(res){
-      that.language = res;
-    })
-  },
-  watch: {
-    language(newVal) {
-      // 语言变化时执行逻辑
-      this.listReview();
-    }
-  },
-  methods: {
-    handleDelete(row) {
-      const ids = row.id || this.ids;
-      this.$confirm('是否确认删除该数据项?').then(() => {
-        delReview(ids).then(res=>{
-          if(res.code===200){
-            this.listReview();
-            this.$message({
-              type: 'success',
-              message: this.$t('mendian.successful')
-            });
-          }else{
-            this.$message({
-              type: 'info',
-              message: this.$t('mendian.Deletefailed')
-            });
-          }
-        }).catch(() => {});
-      })
-    },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const id = row.id;
-      getReview(id).then(response => {
-        this.form = response.data;
-        this.open = true;
-        this.text = this.$t('review.ck');
-        // 关键:如果是减免个别商品,并且有 spId,查商品详情
-      });
-    },
-    reset() {
-      this.form = {
-        id: null,
-        ddId: null,
-        score: null,
-        cretim: null,
-        content: null,
-        userId: null,
-        images:null,
-        anonymous: null
-      };
-
-    },
-
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    listReview() {
-      var that = this;
-      that.loding = true;
-      listReview(this.queryParams).then(response => {
-        that.loding = false;
-        this.total = response.data.total;
-        this.tableData = response.data.records;
-      });
-    },
-
-    //翻页
-    handleSizeChange(val) {
-      // console.log(`每页 ${val} 条`);
-      this.queryParams.size = val;
-      this.listReview();
-    },
-    handleCurrentChange(val) {
-      // console.log(`当前页: ${val}`);
-      this.queryParams.page = val;
-      this.listReview();
-    },
-    handleAvatarlogo(res, file) {
-      // this.upimg = URL.createObjectURL(file.raw);
-      this.form.poster = file.response.data;
-      // console.log('上传图片',file.response);
-
-    },
-
-    beforeAvatarUpload(file) {
-      const isJPG = file.type === 'image/jpeg';
-      const isLt2M = file.size / 1024 / 1024 < 2;
-
-      if (!isJPG) {
-        this.$message.error(this.$t('quanyi.ItcanonlyJPG'));
-      }
-      if (!isLt2M) {
-        this.$message.error(this.$t('quanyi.Cannotexceed'));
-      }
-      return isJPG && isLt2M;
-    },
-
-
-
-  }
-}
-</script>
-
-<style>
-/* 无图片提示样式 */
-.no-images {
-  color: #999;
-  font-style: italic;
-  padding: 10px;
-  border: 1px dashed #eee;
-  border-radius: 4px;
-  text-align: center;
-}
-.avatar-uploader .el-upload {
-  border: 1px dashed #d9d9d9;
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-}
-
-.avatar-uploader .el-upload:hover {
-  border-color: #409EFF;
-}
-
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 100px;
-  height: 100px;
-  line-height: 100px;
-  text-align: center;
-}
-
-.avatar {
-  width: 100px;
-  height: 100px;
-  display: block;
-}
-
-/* 图片容器 - 水平排列 */
-.image-container {
-  display: flex;
-  flex-wrap: wrap; /* 不换行 */
-  overflow-x: auto;  /* 水平滚动(当图片多时) */
-  gap: 10px;         /* 图片间距 */
-}
-
-/* 图片包裹容器 */
-.image-wrapper {
-  position: relative;
-}
-</style>

+ 0 - 578
foodie_sj_vue/src/views/index.vue

@@ -1,578 +0,0 @@
-<template>
-	<div class="lbody">
-		<div class="zuobian">
-			<div style="background-color: #ffffff;">
-				<div style="padding: 20px;">
-					<div>{{$t('index.newdd')}}</div>
-					<div style="display: flex;align-items: center;padding-top: 20px;">
-						<el-button type="text" :class="queryParams.mdId==item.id?'mdyx':'mdwx'" v-for="item in mdlist" @click="xuanzemd(item)">{{item.posName}}</el-button>
-					</div>
-					<div style="display: flex;align-items: center;padding-top: 5px;">
-						<el-button type="text" :class="yxlex==idx?'lxyx':'lxwx'" v-for="(item,idx) in ddleix" @click="xzleixing(item,idx)">{{generateTitle(item.name)}}</el-button>
-					</div>
-				</div>
-				<!-- 查询区域 -->
-				<el-row :gutter="10" style="margin-bottom: 5px;margin-left: 20px">
-				  <el-col :span="12" style="display: flex; align-items: center;">
-				    <el-date-picker
-				      v-model="queryParams.createTimeRange"
-				      type="daterange"
-				      range-separator="-"
-				      :start-placeholder="$t('index.startTime')"
-				      :end-placeholder="$t('index.endTime')"
-				      style="width: 260px; margin-right: 10px;"
-              value-format="yyyy-MM-dd"
-				    />
-				    <el-button type="primary" icon="el-icon-search" @click="onDateRangeSearch">{{$t('foots.search')}}</el-button>
-				    <el-button icon="el-icon-refresh" @click="onDateRangeReset" style="margin-left: 8px;">{{$t('foots.reset') || '重置'}}</el-button>
-				  </el-col>
-				</el-row>
-				<!-- 导出按钮单独一行 -->
-				<el-row :gutter="10" style="margin-bottom: 5px;margin-left: 20px">
-				  <el-col :span="1.5">
-				    <el-button
-				      type="primary"
-				      plain
-				      icon="el-icon-download"
-				      size="mini"
-				      @click="handleExport"
-				    >{{ $t('index.export') }}</el-button>
-				  </el-col>
-				</el-row>
-				<el-table
-					v-loading="loding"
-					:data="tableData"
-					style="width: 100%">
-					<el-table-column
-						prop="ddId"
-						:label="$t('index.ddid')"
-						width="120">
-					</el-table-column>
-					<el-table-column
-						prop="cretim"
-						:label="$t('index.cretim')"
-						width="140">
-					</el-table-column>
-					<el-table-column
-						prop="amount"
-						:label="$t('index.amount')"
-						width="80">
-					</el-table-column>
-					<el-table-column
-						prop="jvli"
-						:label="$t('index.jvli')"
-						width="130">
-					</el-table-column>
-					<el-table-column :label="$t('index.ddodr')" width="250">
-						<template slot-scope="scope">
-							<div style="display: flex;align-items: center;padding: 3px 0;" v-for="item in scope.row.food">
-								<div style="margin-right: 10px;">{{item.name+'x'+item.number}}</div>
-								<div style="margin-right: 5px;
-									background-color: #ffaa00;
-									padding: 2px 5px;color: #ffffff;
-									border-radius: 3px;font-size: 10px;" v-for="os in item.ask"
-								>{{os}}</div>
-							</div>
-						</template>
-					</el-table-column>
-					<el-table-column
-						prop="type"
-						:label="$t('index.type')"
-						width="80">
-						<template slot-scope="scope">
-							<div>{{scope.row.type==1?$t('index.ziqu'):scope.row.type==2?$t('index.tangs'):$t('index.waisong')}}</div>
-						</template>
-					</el-table-column>
-					<el-table-column
-						prop="collectPayment"
-						:label="$t('index.collectPayment')"
-						width="120">
-						<template slot-scope="scope">
-							<div>{{scope.row.collectPayment==0?$t('index.nos'):$t('index.yes')}}</div>
-						</template>
-					</el-table-column>
-					<el-table-column
-						fixed="right"
-						:label="$t('index.right')"
-						:width="$t('loding.language')=='vi'?'180':'110'">
-						<template slot-scope="scope">
-							<el-button @click="handleClick(scope.row)" type="text" size="small">{{$t('index.chak')}}</el-button>
-							<el-button v-if="scope.row.state<2" type="text" size="small" @click="jiedananniu({id:scope.row.id,state:2},2)">{{$t('index.jiedan')}}</el-button>
-							<el-button type="text" size="small" v-if="(scope.row.state==2||scope.row.state==3)&&scope.row.diningStatus==0"  @click="jiedananniu({id:scope.row.id,diningStatus:1},2)">{{$t('index.chucan')}}</el-button>
-						</template>
-					</el-table-column>
-				</el-table>
-				<div style="width: 100%;display: flex;justify-content: flex-end;">
-					<el-pagination
-						@size-change="handleSizeChange"
-						@current-change="handleCurrentChange"
-						:current-page="queryParams.page"
-						:page-size="queryParams.size"
-						layout="total, prev, pager, next"
-						:total="total">
-					</el-pagination>
-				</div>
-			</div>
-		</div>
-		<el-dialog  :title="$t('index.tishi')" :visible.sync="visible" width="300px" append-to-body>
-			<div>{{$t('index.tisiyu')}}</div>
-			<div slot="footer" class="dialog-footer">
-				<el-button @click="guanbist">{{$t('index.quxiao')}}</el-button>
-				<el-button @click="setorderzhgt">{{$t('index.qued')}}</el-button>
-			</div>
-		</el-dialog>
-		<!-- 详请弹窗 -->
-		<el-dialog :title="$t('index.xiangq')" :visible.sync="open" width="700px" append-to-body>
-		  <div>
-			  <div style="display: flex;align-items: center;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.ddid')}}:</div>
-				  <div>{{neirxq.ddId}}</div>
-			  </div>
-			  <div style="display: flex;align-items: center;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.cretim')}}:</div>
-				  <div>{{neirxq.cretim}}</div>
-			  </div>
-			  <div style="display: flex;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.address')}}:</div>
-				  <div v-if="psdizhi">
-					  <div>{{psdizhi.name+' '+psdizhi.phone}}</div>
-					  <div>{{psdizhi.country+psdizhi.city+psdizhi.area+psdizhi.address}}</div>
-				  </div>
-			  </div>
-			  <div style="display: flex;align-items: center;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.amount')}}:</div>
-				  <div>₫{{neirxq.amount}}</div>
-			  </div>
-			  <div style="display: flex;align-items: center;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.jvli')}}:</div>
-				  <div>{{neirxq.jvli}}km</div>
-			  </div>
-			  <div style="display: flex;align-items: center;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.freight')}}:</div>
-				  <div>₫{{neirxq.freight}}</div>
-			  </div>
-			  <div style="display: flex;margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;">{{$t('index.qishou')}}:</div>
-				  <div style="display: flex;" v-if="qisou">
-					  <img :src="murl+qisou.avatar" style="width: 40px;height: 40px;border-radius: 5px;">
-					  <div style="margin-left: 10px;">
-						  <div style="font-weight: bold;margin-bottom: 5px;">{{qisou.nickName}}</div>
-						  <div>{{qisou.phone}}</div>
-					  </div>
-				  </div>
-			  </div>
-        <!-- 新增:促销活动信息 -->
-        <div style="margin: 20px 0; padding: 10px; background: #fff7e6; border-radius: 6px;">
-          <div style="font-weight: bold; color: #ff5500; margin-bottom: 5px;">{{$t("index.cxhdxx")}}</div>
-          <div v-if="neirxq.salesName || neirxq.mdSalesName">
-            <div v-if="neirxq.salesName">
-              {{$t("index.ptcxhd")}}:{{ neirxq.salesName }}
-              <span v-if="neirxq.salesReduction">({{$t("index.jm")}}:{{ neirxq.salesReduction }})</span>
-            </div>
-            <div v-if="neirxq.mdSalesName">
-              {{$t("index.sjcxhd")}}:{{ neirxq.mdSalesName }}
-              <span v-if="neirxq.mdSalesReduction">({{$t("index.jm")}}:{{ neirxq.mdSalesReduction }})</span>
-            </div>
-          </div>
-          <div v-else>{{$t("index.none")}}</div>
-        </div>
-        <!-- 新增:优惠券信息 -->
-        <div style="margin: 20px 0; padding: 10px; background: #e6f7ff; border-radius: 6px;">
-          <div style="font-weight: bold; color: #1890ff; margin-bottom: 5px;">{{$t("index.yhqxx")}}</div>
-          <div v-if="neirxq.yhName || neirxq.mdYhName">
-            <div v-if="neirxq.yhName">
-              {{$t("index.ptyhq")}}:{{ neirxq.yhName }}
-              <span v-if="neirxq.discountAmount">({{$t("index.yhje")}}:{{ neirxq.discountAmount }})</span>
-            </div>
-            <div v-if="neirxq.mdYhName">
-              {{$t("index.sjyhq")}}:{{ neirxq.mdYhName }}
-              <span v-if="neirxq.mdDiscountAmount">({{$t("index.yhje")}}:{{ neirxq.mdDiscountAmount }})</span>
-            </div>
-          </div>
-          <div v-else>{{$t("index.none")}}</div>
-        </div>
-        <!-- 新增:积分使用情况 -->
-        <div style="margin: 20px 0; padding: 10px; background: #f3e6ff; border-radius: 6px;">
-          <div style="font-weight: bold; color: #722ed1; margin-bottom: 5px;">{{$t("index.jfsyqk")}}</div>
-          <div v-if="neirxq.points && neirxq.pointsReduction">
-            <div v-if="neirxq.points">
-              {{$t("index.jfsysl")}}:{{ neirxq.points }}
-              <span v-if="neirxq.pointsReduction">({{$t("index.jfdkje")}}:{{ neirxq.pointsReduction }})</span>
-            </div>
-          </div>
-          <div v-else>{{$t("index.none")}}</div>
-        </div>
-			  <div style="margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;margin-bottom: 20px;">{{$t('index.foods')}}:</div>
-				  <el-row style="margin:0 0 0 120px">
-				    <el-col :span="8" v-for="item in neirxq.food" offset="1" style="margin-bottom: 10px;width:200px">
-				      <el-card :body-style="{ padding: '0px' }">
-				        <img :src="murl+item.image" class="image">
-				        <div style="padding: 14px;display: flex;flex-direction: column;">
-				          <span>{{item.name}}×{{item.number}}</span>
-						  <span style="color: #ff557f;">₫{{format(item.price)}}</span>
-						  <div style="display: flex;align-items: center;flex-wrap: wrap;">
-							  <el-tag style="margin: 5px 5px;" type="danger" v-for="or in item.ask">{{or}}</el-tag>
-						  </div>
-				        </div>
-				      </el-card>
-				    </el-col>
-				  </el-row>
-			  </div>
-			  <div  style="margin: 20px 0;">
-				  <div style="display: flex;justify-content: flex-end;width: 160px;margin-right: 20px;margin-bottom: 20px;">{{$t('index.beizu')}}:</div>
-				  <div>{{neirxq.remarks}}</div>
-			  </div>
-		  </div>
-		  <div slot="footer" class="dialog-footer">
-			<el-button v-if="neirxq.state<2" @click="setorderzhgt({id:neirxq.id,state:2})">{{$t('index.jiedan')}}</el-button>
-			<el-button v-if="(neirxq.state==2||neirxq.state==3)&&neirxq.diningStatus==0" @click="setorderzhgt({id:neirxq.id,diningStatus:1})">{{$t('index.chucan')}}</el-button>
-		    <el-button @click="cancel">{{$t('index.guanbi')}}</el-button>
-		  </div>
-		</el-dialog>
-		<div class="youbian">
-			<el-col :span="8" style="width:18vw">
-			    <el-card class="shujzu">
-			      <img class="touxia" :src="murl+user.avatar">
-			      <div class="shujzu" style="padding: 10px;">
-			        <div style="font-size: 25px;font-weight: bold;margin-bottom: 5px;">{{user.nickName}}</div>
-					<div style="font-size: 15px;">{{user.userName}}</div>
-					<div style="padding: 3px 10px;background-color: #ffaa00;margin-top: 10px;color: #ffffff;border-radius: 4px;">{{user.userType=='1'?$t('index.shus'):user.userType=='2'?$t('index.sqsu'):$t('index.user')}}</div>
-			      </div>
-			    </el-card>
-			</el-col>
-			<div class="hengzy">
-				<div>
-					<div class="wzsla">{{ustj.stroe}}</div>
-					<div class="xiaozi">{{$t('index.dpshu')}}</div>
-				</div>
-				<div>
-					<div class="wzsla">{{ustj.dtshour}}</div>
-					<div class="xiaozi">{{$t('index.ddsour')}}</div>
-				</div>
-				<div>
-					<div class="wzsla">{{ustj.dtorder}}</div>
-					<div class="xiaozi">{{$t('index.dddingd')}}</div>
-				</div>
-			</div>
-			<div>
-				<div class="hxiag">
-					<div style="display: flex;align-items: center;justify-content: center;width: 80px;height: 80px;background-color: #df9797;">
-						<img style="width: 40px;height: 40px;" src="../assets/zshour.png" alt="" />
-					</div>
-					<div style="margin-left: 20px;font-size: 13px;color: #787878;">
-						<div style="font-size: 22px;font-weight: bold;color: #ff557f;">{{ustj.qbshour}}</div>
-						<div>{{$t('index.zongsr')}}</div>
-					</div>
-				</div>
-				<div class="hxiag">
-					<div style="display: flex;align-items: center;justify-content: center;width: 80px;height: 80px;background-color: #cfe4ee;">
-						<img style="width: 40px;height: 40px;" src="../assets/ddlan.png" alt="" />
-					</div>
-					<div style="margin-left: 20px;font-size: 13px;color: #787878;">
-						<div style="font-size: 22px;font-weight: bold;color: #55aaff;">{{ustj.qborder}}</div>
-						<div>{{$t('index.zddlng')}}</div>
-					</div>
-				</div>
-				<div class="hxiag">
-					<div style="display: flex;align-items: center;justify-content: center;width: 80px;height: 80px;background-color: #dfddbd;">
-						<img style="width: 40px;height: 40px;" src="../assets/ktixian.png" alt="" />
-					</div>
-					<div style="margin-left: 20px;font-size: 13px;color: #787878;">
-						<div style="font-size: 22px;font-weight: bold;color: #ffaa00;">{{ustj.ketixian}}</div>
-						<div>{{$t('index.ketixan')}}</div>
-					</div>
-				</div>
-			</div>
-		</div>
-	</div>
-</template>
-
-<script>
-	import {getindex,getshordlist,getstorelist,setorder} from '@/api/index';
-	import {generateTitle} from '../utils/i18n'
-  import {download} from '@/router/request'
-	export default{
-		name:"index",
-		data(){
-			return {
-				loding:false,
-				murl: process.env.VUE_APP_BACKEND_URL,
-				user:{},
-				ustj:{},
-				open:false,
-				visible:false,
-				ddleix:[{
-					name:'Unaccepted',
-					type:'z01',
-					dstate:''
-				},{
-					name:'Accepted',
-					type:'z23',
-					dstate:'0'
-				},{
-					name:'Mealalreadyserved',
-					type:'',
-					dstate:'1'
-				},{
-					name:'RefundAftersales',
-					type:'z6789',
-					dstate:''
-				}],
-				yxlex:0,
-				// 查询参数
-				total: 0,
-				queryParams: {
-				  page: 1,
-				  size: 10,
-				  mdId:'',
-				  state: 'z01',
-				  diningStatus: '',
-				  createTimeRange: []
-				},
-				dqxzmd:'',
-				tableData: [],
-				mdlist:[],
-				neirxq:{},
-				psdizhi:{},
-				qisou:{},
-				orderrow:{},
-				tjzt:0
-			}
-		},
-		created() {
-			this.user = JSON.parse(localStorage.getItem('user'));
-			// console.log('1111111111',this.user);
-			this.getshindex();
-			this.getmendlist(0);
-		},
-
-		methods:{
-			generateTitle,
-			format(str) {
-			  var arr = [];
-			    var counter = 0;
-			    str = (str || 0).toString().split("");
-			    for (var i = str.length - 1; i >= 0; i--) {
-			      counter++;
-			      arr.unshift(str[i]);
-			      if (!(counter % 3) && i !== 0) {
-			        arr.unshift(",");
-			      }
-			    }
-			    return arr.join("");
-			},
-			setorderzhgt(order){
-				this.orderrow = this.tjzt==2?this.orderrow:order;
-				setorder(this.orderrow).then(res=>{
-					// console.log('提交结果',res)
-					if(res.code==200){
-						if(this.tjzt==0){
-							this.cancel()
-						}else{
-							this.guanbist();
-						}
-						this.getshddlist();
-					}
-				})
-			},
-			//接单弹窗
-			jiedananniu(order,zt){
-				this.orderrow = order;
-				this.tjzt = zt;
-				this.visible = true;
-			},
-			guanbist(){
-				this.orderrow = {};
-				this.tjzt = 0;
-				this.visible = false;
-			},
-			// 关闭弹窗按钮
-			cancel() {
-			  this.open = false;
-			},
-			handleClick(row){
-				this.neirxq = row;
-				this.orderrow = row;
-				this.psdizhi = row.shaddress;
-				this.qisou = row.qishou;
-				this.open = true;
-			},
-			//获取首页统计
-			getshindex(){
-				getindex(this.user.userId).then(response => {
-					// console.log("获取用户统计",response);
-					this.ustj = response.data;
-				});
-			},
-			//选择门店
-			xuanzemd(item){
-				this.queryParams.mdId = item.id;
-				this.getmendlist(1);
-			},
-			//选择订单类型
-			xzleixing(item,idx){
-				this.yxlex = idx;
-				this.queryParams.state = item.type;
-				this.queryParams.diningStatus = item.dstate;
-				this.getmendlist(1);
-			},
-			// 获取门店列表
-			getmendlist(lx){
-				getstorelist().then(response => {
-					// console.log("获取门店列表",response);
-					this.mdlist = response.data || [];
-					if(lx==0 && response.data && response.data.length > 0){
-						this.queryParams.mdId = response.data[0].id;
-					}
-					this.getshddlist();
-				});
-			},
-			//获取门店订单
-			getshddlist(){
-				this.loding = true;
-				// 拆分时间范围
-				let params = { ...this.queryParams };
-				if (params.createTimeRange && Array.isArray(params.createTimeRange) && params.createTimeRange.length === 2) {
-				  params.startTime = params.createTimeRange[0];
-				  params.endTime = params.createTimeRange[1];
-				}
-				delete params.createTimeRange;
-				getshordlist(params).then(response => {
-					this.total = response.data.total;
-					var list = response.data.list;
-					for(let i=0;i<list.length;i++){
-					  list[i].amount = this.format(list[i].amount);
-					  list[i].freight = this.format(list[i].freight);
-					  list[i].priceAll = this.format(list[i].priceAll);
-					}
-					this.tableData = list;
-					// console.log("获取订单",response);
-					this.loding = false;
-				});
-			},
-			//翻页
-			handleSizeChange(val) {
-				// console.log(`每页 ${val} 条`);
-				this.queryParams.size = val;
-				this.getshddlist();
-			},
-			handleCurrentChange(val) {
-				// console.log(`当前页: ${val}`);
-				this.queryParams.page = val;
-				this.getshddlist();
-			},
-      /** 导出按钮操作 */
-      handleExport() {
-        console.log('导出按钮操作')
-        console.log(this.$t)
-        // 拆分时间范围
-        let params = { ...this.queryParams };
-        if (params.createTimeRange && Array.isArray(params.createTimeRange) && params.createTimeRange.length === 2) {
-          params.startTime = params.createTimeRange[0];
-          params.endTime = params.createTimeRange[1];
-        }
-        delete params.createTimeRange;
-        download('/index/export', {
-          ...params
-        }, `order_${new Date().getTime()}.xlsx`, {
-          headers: {
-            isToken: true
-          }
-        },this.$t)
-      },
-      onDateRangeChange() {
-        this.getshddlist();
-      },
-      onDateRangeSearch() {
-        this.getshddlist();
-      },
-      onDateRangeReset() {
-        this.queryParams.createTimeRange = [];
-        this.getshddlist();
-      }
-		}
-	}
-</script>
-
-<style>
-	.image{
-		width: 200px;
-		height: 150px;
-	}
-	.mdyx{
-		margin-right: 10px;
-		font-size: 18px;
-		font-weight: bold;
-	}
-	.mdwx{
-		margin-right: 10px;
-		font-size: 18px;
-		color:#b9b9b9;
-	}
-	.lxyx{
-		margin-right: 10px;
-		font-size: 12px;
-		font-weight: bold;
-	}
-	.lxwx{
-		margin-right: 10px;
-		font-size: 12px;
-		color:#b9b9b9;
-	}
-	.hxiag{
-		display: flex;
-		align-items: center;
-		width: 18vw;
-		background-color: #fafafa;
-		margin-top: 20px;
-	}
-	.lbody{
-		display: flex;
-		justify-content: space-between;
-	}
-	.hengzy{
-		display: flex;
-		align-items: center;
-		justify-content: space-around;
-		width: 18vw;
-		background-color: #fafafa;
-		padding: 20px 10px;
-		margin-top: 20px;
-	}
-	.wzsla{
-		font-size: 20px;
-		font-weight: bold;
-	}
-	.xiaozi{
-		font-size: 13px;
-		color: #b1b5ba;
-	}
-	.zuobian{
-		width: 60vw;
-		height: 88vh;
-		background-color: #ecf2f9;
-		border-radius: 10px;
-		padding: 20px;
-	}
-	.youbian{
-		width: 21vw;
-		height: 88vh;
-		background-color: #ecf2f9;
-		border-radius: 10px;
-		padding: 20px;
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-	}
-	.shujzu{
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-	}
-	.touxia{
-		width: 150px;
-		height: 150px;
-		border-radius: 75px;
-	}
-</style>

+ 0 - 11
foodie_sj_vue/vue.config.js

@@ -1,11 +0,0 @@
-const { defineConfig } = require('@vue/cli-service')
-module.exports = defineConfig({
-  transpileDependencies: true,
-  chainWebpack: config => {
-        config.plugin('html')
-		.tap(args => {
-			args[0].title = 'cte';
-			return args;
-		})
-  },
-})

BIN
req_image.png


+ 12 - 0
ruoyi-admin/pom.xml

@@ -114,6 +114,18 @@
             <version>5.2.1</version>
         </dependency>
 
+        <!-- ZXing 二维码生成 -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.5.2</version>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/app/order/MyTestController.java

@@ -29,7 +29,7 @@ public class MyTestController {
     public AjaxResult testWallect(@RequestHeader String token, @RequestParam BigDecimal balance){
         JwtUtil jwtUtil = new JwtUtil();
         String id = jwtUtil.getusid(token);
-        UserWallet userWallet = userWalletService.getOne(new LambdaQueryWrapper<UserWallet>().eq(UserWallet::getUserId, Long.valueOf(id)));
+        UserWallet userWallet = userWalletService.selectByUserId(Long.valueOf(id));
         String lockKey = "user:wallet:"+id;
         RLock lock=redissonClient.getLock(lockKey);
         try {

+ 2 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java

@@ -1460,6 +1460,7 @@ public class PosOrderController extends BaseController {
             }
             LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
             walletQuery.eq(UserWallet::getUserId, userId);
+            walletQuery.isNull(UserWallet::getStoreId);
             UserWallet userWallet = userWalletService.getOne(walletQuery);
             if (ObjectUtil.isNotNull(userWallet)) {
                 if (userWallet.getPointsWallet().compareTo(Long.valueOf(orderDTO.getPoints())) >= 0) {
@@ -1777,6 +1778,7 @@ public class PosOrderController extends BaseController {
     public void returnPoints(Long userId, Long ddId, Long points) {
         LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
         walletQuery.eq(UserWallet::getUserId, userId);
+        walletQuery.isNull(UserWallet::getStoreId);
         UserWallet userWallet = userWalletService.getOne(walletQuery);
         PointsTransaction transaction = pointsTransactionService.getOne(new LambdaQueryWrapper<PointsTransaction>().eq(PointsTransaction::getDdId, ddId.toString()).eq(PointsTransaction::getType, "2"));
         //该订单不存在退回的积分记录

+ 1 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderRatingController.java

@@ -85,6 +85,7 @@ public class PosOrderRatingController extends BaseController
         if (control.getReviewEnable().equals(1L)) {
             LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
             walletQuery.eq(UserWallet::getUserId, userid);
+            walletQuery.isNull(UserWallet::getStoreId);
             UserWallet userWallet = userWalletService.getOne(walletQuery);
 
             if (userWallet == null) {

+ 1 - 0
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosReviewController.java

@@ -161,6 +161,7 @@ public class PosReviewController extends BaseController {
         if (control.getReviewEnable().equals(1L)) {
             LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
             walletQuery.eq(UserWallet::getUserId, userid);
+            walletQuery.isNull(UserWallet::getStoreId);
             UserWallet userWallet = userWalletService.getOne(walletQuery);
 
             if (userWallet == null) {

+ 5 - 5
ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java

@@ -118,16 +118,16 @@ public class UserOrderController extends BaseController {
         LambdaQueryWrapper<OperatingHours> wrapper = new LambdaQueryWrapper<>();
         wrapper.in(OperatingHours::getMdId, mdIdList);
         List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
-        if(!input.getItems().isEmpty() && input.getItems().size()>1){
-            throw new ServiceException("一次只能下单一个商家的订单");
-        }
+        boolean isMultiStore = input.getItems().size() > 1;
         // 循环items,为每个item创建一条PosOrder
+        int index = 0;
         for (OrderCreatItem item : input.getItems()) {
 
             // 检查门店是否开放
             checkStoreOpen(storeList,hourslist,item);
-            int index = input.getItems().indexOf(item) + 1;
-            String subddId = ddId;
+            index++;
+            // 单店铺:子订单号与父订单一致;多店铺:子订单号追加序号
+            String subddId = isMultiStore ? ddId + String.format("%03d", index) : ddId;
             PosOrder posOrder = new PosOrder();
             posOrder.setIsDisplay(false);
             handleIsDisplay(posOrder);

+ 4 - 4
ruoyi-admin/src/main/java/com/ruoyi/app/pay/UserBillingController.java

@@ -94,8 +94,8 @@ public class UserBillingController extends BaseController {
         QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
         String userType = user.getUserType();
 
-        if ("1".equals(userType)) {
-            // 商家:查自己名下所有门店的账单
+        if ("1".equals(userType) || "3".equals(userType)) {
+            // 商家/夜市用户:查自己名下所有门店的账单
             wrapper.eq("user_id", userId);
             if (mdId != null) {
                 wrapper.eq("md_id", mdId);
@@ -158,12 +158,12 @@ public class UserBillingController extends BaseController {
         QueryWrapper<UserBilling> wrapper = new QueryWrapper<>();
         String userType = user.getUserType();
 
-        if ("1".equals(userType)) {
+        if ("1".equals(userType) || "3".equals(userType)) {
             wrapper.eq("user_id", userId);
             if (mdId != null) {
                 wrapper.eq("md_id", mdId);
             }
-        } else if ("3".equals(userType)) {
+        } else if ("4".equals(userType)) {
             Long storeId = user.getStoreId();
             if (storeId == null) {
                 return error("未关联门店");

+ 1 - 1
ruoyi-admin/src/main/java/com/ruoyi/app/pay/WalletController.java

@@ -142,7 +142,7 @@ public class WalletController extends BaseController {
     public AjaxResult getWalletInfo(@RequestHeader String token) {
         JwtUtil jwtUtil = new JwtUtil();
         String userId = jwtUtil.getusid(token);
-        UserWallet userWallet = userWalletService.getOne(new LambdaQueryWrapper<UserWallet>().eq(UserWallet::getUserId, Long.valueOf(userId)));
+        UserWallet userWallet = userWalletService.selectByUserId(Long.valueOf(userId));
         return AjaxResult.success(userWallet);
     }
 

+ 21 - 27
ruoyi-admin/src/main/java/com/ruoyi/app/service/WalletService.java

@@ -80,9 +80,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -104,7 +102,8 @@ public class WalletService {
                     // 5. 乐观锁更新钱包
                     LambdaQueryWrapper<UserWallet> updateQuery = new LambdaQueryWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion()); // 版本控制
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
 
                     userWallet.setPointsWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
@@ -163,9 +162,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -192,7 +189,8 @@ public class WalletService {
                     // 6. 乐观锁更新钱包
                     LambdaQueryWrapper<UserWallet> updateQuery = new LambdaQueryWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
 
                     userWallet.setPointsWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
@@ -249,9 +247,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -271,7 +267,8 @@ public class WalletService {
                     // 4. 乐观锁更新钱包
                     LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
                     userWallet.setBalanceWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
 
@@ -328,9 +325,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -340,7 +335,8 @@ public class WalletService {
                     // 4. 乐观锁更新钱包
                     LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
 
                     userWallet.setBalanceWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
@@ -418,7 +414,8 @@ public class WalletService {
                     // 5. 乐观锁更新钱包
                     LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
                     userWallet.setBalanceWallet(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
@@ -461,8 +458,7 @@ public class WalletService {
             throw new ServiceException("用户ID不能为空");
         }
         LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-        walletQuery.eq(UserWallet::getUserId, userId);
-        UserWallet userWallet = userWalletService.getOne(walletQuery);
+        UserWallet userWallet = userWalletService.selectByUserId(userId);
         if (userWallet == null) {
             throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
         }
@@ -505,9 +501,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -522,7 +516,8 @@ public class WalletService {
                     // 4. 乐观锁更新钱包
                     LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
                     userWallet.setBlockedFunds(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);
                     boolean updateSuccess = userWalletService.update(userWallet, updateQuery);
@@ -584,9 +579,7 @@ public class WalletService {
                 boolean releaseInFinally = true;
                 try {
                     // 2. 获取用户钱包
-                    LambdaQueryWrapper<UserWallet> walletQuery = new LambdaQueryWrapper<>();
-                    walletQuery.eq(UserWallet::getUserId, userId);
-                    UserWallet userWallet = userWalletService.getOne(walletQuery);
+                    UserWallet userWallet = userWalletService.selectByUserId(userId);
                     if (userWallet == null) {
                         throw new ServiceException(MessageUtils.message("no.user.wallet.not.exist"));
                     }
@@ -603,7 +596,8 @@ public class WalletService {
                     // 4. 乐观锁更新钱包
                     LambdaUpdateWrapper<UserWallet> updateQuery = new LambdaUpdateWrapper<>();
                     updateQuery.eq(UserWallet::getUserId, userId)
-                            .eq(UserWallet::getVersion, userWallet.getVersion());
+                            .eq(UserWallet::getVersion, userWallet.getVersion())
+                            .isNull(UserWallet::getStoreId);
 
                     userWallet.setBlockedFunds(newBalance);
                     userWallet.setVersion(userWallet.getVersion() + 1);

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است