Browse Source

feat: 碳排放

sunxiao 9 tháng trước cách đây
mục cha
commit
fd280dfbb8
88 tập tin đã thay đổi với 4792 bổ sung46 xóa
  1. 9 0
      auto-imports.d.ts
  2. 43 0
      components.d.ts
  3. 442 19
      package-lock.json
  4. 6 1
      package.json
  5. 2 3
      src/App.vue
  6. 26 0
      src/api/carbon.js
  7. 8 0
      src/api/env.js
  8. BIN
      src/assets/fonts/YouSheBiaoTiHei.ttf
  9. BIN
      src/assets/images/carbon/Group 1321315504 (1).png
  10. BIN
      src/assets/images/carbon/Group 1321315573.png
  11. BIN
      src/assets/images/carbon/bg-3d.png
  12. BIN
      src/assets/images/carbon/bg-3d_副本.png
  13. BIN
      src/assets/images/carbon/bg-board-bottom.png
  14. BIN
      src/assets/images/carbon/bg-board-one.png
  15. BIN
      src/assets/images/carbon/bg-board-right.png
  16. BIN
      src/assets/images/carbon/bg-btn-1.png
  17. BIN
      src/assets/images/carbon/bg-btn-2.png
  18. BIN
      src/assets/images/carbon/bg-btn-3.png
  19. BIN
      src/assets/images/carbon/bg-btn-4.png
  20. BIN
      src/assets/images/carbon/bg-calendar-direction.png
  21. BIN
      src/assets/images/carbon/bg-calendar.png
  22. BIN
      src/assets/images/carbon/bg-footer.png
  23. BIN
      src/assets/images/carbon/bg-header.png
  24. BIN
      src/assets/images/carbon/bg-large-title.png
  25. BIN
      src/assets/images/carbon/bg-large-title1.png
  26. BIN
      src/assets/images/carbon/bg-screen-top.png
  27. BIN
      src/assets/images/carbon/bg-screen.png
  28. BIN
      src/assets/images/carbon/bg-title-data.png
  29. BIN
      src/assets/images/carbon/bg-title-energy.png
  30. BIN
      src/assets/images/carbon/bg-title-energy1.png
  31. BIN
      src/assets/images/carbon/bg-title-left-top.png
  32. BIN
      src/assets/images/carbon/bg-title-right-top.png
  33. BIN
      src/assets/images/carbon/bg-title.png
  34. BIN
      src/assets/images/carbon/bg.png
  35. BIN
      src/assets/images/carbon/icon-btn_back.png
  36. BIN
      src/assets/images/carbon/icon-up.png
  37. 125 0
      src/assets/images/carbon/svg/icon-borad-five.svg
  38. 120 0
      src/assets/images/carbon/svg/icon-borad-four.svg
  39. 125 0
      src/assets/images/carbon/svg/icon-borad-one.svg
  40. 19 0
      src/assets/images/carbon/svg/icon-borad-six.svg
  41. 19 0
      src/assets/images/carbon/svg/icon-borad-three.svg
  42. 20 0
      src/assets/images/carbon/svg/icon-borad-two.svg
  43. 3 0
      src/assets/images/carbon/svg/icon-bottom-left.svg
  44. 3 0
      src/assets/images/carbon/svg/icon-bottom-right.svg
  45. 3 0
      src/assets/images/carbon/svg/icon-down.svg
  46. 3 0
      src/assets/images/carbon/svg/icon-top-left.svg
  47. 3 0
      src/assets/images/carbon/svg/icon-top-right.svg
  48. 3 0
      src/assets/images/carbon/svg/icon-up.svg
  49. BIN
      src/assets/images/carbon/底部.png
  50. BIN
      src/assets/images/carbon/替碳.png
  51. BIN
      src/assets/images/carbon/标题.png
  52. BIN
      src/assets/images/carbon/污水处理.png
  53. BIN
      src/assets/images/carbon/污泥处理.png
  54. 8 0
      src/assets/styles/common.scss
  55. 24 0
      src/assets/svgs/carbon/icon-back.svg
  56. 12 0
      src/assets/svgs/tool/add-symbol.svg
  57. 3 0
      src/assets/svgs/tool/setp-arrow-right.svg
  58. 64 0
      src/components/BaseNumberInput/index.vue
  59. 10 11
      src/components/Chat/ChatAgentInput.vue
  60. 5 0
      src/components/Layout/TheMenu.vue
  61. 5 1
      src/components/index.js
  62. 1 1
      src/composables/useInfinite.js
  63. 73 0
      src/composables/useTable.js
  64. 2 1
      src/main.ts
  65. 16 8
      src/router/index.js
  66. 61 0
      src/views/carbon/components/BaseCard.vue
  67. 104 0
      src/views/carbon/components/BaseDatePicker.vue
  68. 96 0
      src/views/carbon/components/BasePanel.vue
  69. 83 0
      src/views/carbon/components/BaseStep.vue
  70. 162 0
      src/views/carbon/components/BaseTable.vue
  71. 775 0
      src/views/carbon/components/TheDrawerForm.vue
  72. 741 0
      src/views/carbon/components/TheDrawerList.vue
  73. 158 0
      src/views/carbon/components/TheModal.vue
  74. 72 0
      src/views/carbon/components/config.js
  75. 21 0
      src/views/carbon/components/index.js
  76. 247 0
      src/views/carbon/components/screen/DataBorad.vue
  77. 119 0
      src/views/carbon/components/screen/DataScroll.vue
  78. 29 0
      src/views/carbon/components/screen/EchartColumnar.vue
  79. 29 0
      src/views/carbon/components/screen/EchartEnergy.vue
  80. 13 0
      src/views/carbon/components/screen/EchartSewage.vue
  81. 70 0
      src/views/carbon/components/screen/LayoutCard.vue
  82. 381 0
      src/views/carbon/echartOptions/index.js
  83. 376 0
      src/views/carbon/index.vue
  84. 12 0
      src/views/carbon/tools/resetTheme.js
  85. 1 0
      src/views/control/components/BaseInput.vue
  86. 24 1
      src/views/env/index.vue
  87. 4 0
      src/views/screen/ScreenView.vue
  88. 9 0
      vite.config.ts

+ 9 - 0
auto-imports.d.ts

@@ -0,0 +1,9 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+export {}
+declare global {
+
+}

+ 43 - 0
components.d.ts

@@ -0,0 +1,43 @@
+/* eslint-disable */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+export {}
+
+/* prettier-ignore */
+declare module 'vue' {
+  export interface GlobalComponents {
+    BaseButton: typeof import('./src/components/BaseButton/index.vue')['default']
+    BaseCard: typeof import('./src/components/BaseCard/index.vue')['default']
+    BaseInput: typeof import('./src/components/BaseInput/index.vue')['default']
+    BaseNumberInput: typeof import('./src/components/BaseNumberInput/index.vue')['default']
+    BasePopover: typeof import('./src/components/BasePopover/index.vue')['default']
+    BaseTable: typeof import('./src/components/BaseTable/index.vue')['default']
+    ChatAgentInput: typeof import('./src/components/Chat/ChatAgentInput.vue')['default']
+    ChatAnswer: typeof import('./src/components/Chat/ChatAnswer.vue')['default']
+    ChatAsk: typeof import('./src/components/Chat/ChatAsk.vue')['default']
+    ChatBaseCard: typeof import('./src/components/Chat/ChatBaseCard.vue')['default']
+    ChatInput: typeof import('./src/components/Chat/ChatInput.vue')['default']
+    ChatSite: typeof import('./src/components/Chat/ChatSite.vue')['default']
+    ChatText: typeof import('./src/components/Chat/ChatText.vue')['default']
+    ChatWelcome: typeof import('./src/components/ChatWelcome/index.vue')['default']
+    ContactUs: typeof import('./src/components/User/contactUs.vue')['default']
+    EditPassword: typeof import('./src/components/Dialog/editPassword.vue')['default']
+    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    RecodeCardItem: typeof import('./src/components/RecodeCardItem/index.vue')['default']
+    RecodeSquareCardItem: typeof import('./src/components/RecodeSquareCardItem/index.vue')['default']
+    RouterLink: typeof import('vue-router')['RouterLink']
+    RouterView: typeof import('vue-router')['RouterView']
+    SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
+    TheChatView: typeof import('./src/components/Layout/TheChatView.vue')['default']
+    TheControlView: typeof import('./src/components/Layout/TheControlView.vue')['default']
+    TheLogo: typeof import('./src/components/Layout/TheLogo.vue')['default']
+    TheMenu: typeof import('./src/components/Layout/TheMenu.vue')['default']
+    ThePublicLayout: typeof import('./src/components/Layout/ThePublicLayout.vue')['default']
+    TheSubMenu: typeof import('./src/components/Layout/TheSubMenu.vue')['default']
+    TheUserAvatar: typeof import('./src/components/Layout/TheUserAvatar.vue')['default']
+    UserEdit: typeof import('./src/components/User/userEdit.vue')['default']
+    UserTop: typeof import('./src/components/Layout/userTop.vue')['default']
+  }
+}

+ 442 - 19
package-lock.json

@@ -8,10 +8,12 @@
       "name": "temp-vue-3",
       "version": "0.0.0",
       "dependencies": {
+        "@vuepic/vue-datepicker": "^9.0.2",
         "@vueuse/core": "^10.9.0",
         "axios": "^1.6.8",
         "echarts": "^5.5.0",
         "echarts-gl": "^2.0.9",
+        "element-plus": "^2.8.1",
         "highlight.js": "^11.9.0",
         "katex": "^0.16.10",
         "load-awesome": "^1.1.0",
@@ -26,7 +28,8 @@
         "sass-loader": "^14.2.1",
         "three": "^0.166.1",
         "vue": "^3.4.21",
-        "vue-router": "^4.3.0"
+        "vue-router": "^4.3.0",
+        "vue3-seamless-scroll": "^2.0.1"
       },
       "devDependencies": {
         "@digitalacorn/vite-plugin-svg-icons": "^3.0.0-pre.1",
@@ -45,6 +48,8 @@
         "ssh2-sftp-client": "^10.0.3",
         "tailwindcss": "^3.4.4",
         "typescript": "~5.4.0",
+        "unplugin-auto-import": "^0.18.2",
+        "unplugin-vue-components": "^0.27.4",
         "vite": "^5.2.8",
         "vite-plugin-vue-devtools": "^7.0.25",
         "vue-tsc": "^2.0.11"
@@ -76,9 +81,9 @@
       }
     },
     "node_modules/@antfu/utils": {
-      "version": "0.7.8",
-      "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.8.tgz",
-      "integrity": "sha512-rWQkqXRESdjXtc+7NRfK9lASQjpXJu1ayp7qi1d23zZorY+wBHVLHHoVcMsEnkqEBWTFqbztO7/QdJFzyEcLTg==",
+      "version": "0.7.10",
+      "resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
+      "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
       "dev": true,
       "funding": {
         "url": "https://github.com/sponsors/antfu"
@@ -704,6 +709,14 @@
         "vue": "^3.0.11"
       }
     },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+      "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/@digitalacorn/vite-plugin-svg-icons": {
       "version": "3.0.0-pre.1",
       "resolved": "https://registry.npmmirror.com/@digitalacorn/vite-plugin-svg-icons/-/vite-plugin-svg-icons-3.0.0-pre.1.tgz",
@@ -723,6 +736,14 @@
         "vite": ">=2.9.16"
       }
     },
+    "node_modules/@element-plus/icons-vue": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
+      "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
     "node_modules/@emotion/hash": {
       "version": "0.8.0",
       "resolved": "https://registry.npmmirror.com/@emotion/hash/-/hash-0.8.0.tgz",
@@ -1096,6 +1117,28 @@
         "node": ">=12"
       }
     },
+    "node_modules/@floating-ui/core": {
+      "version": "1.6.7",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.7.tgz",
+      "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.7"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.6.10",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.10.tgz",
+      "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==",
+      "dependencies": {
+        "@floating-ui/core": "^1.6.0",
+        "@floating-ui/utils": "^0.2.7"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.7.tgz",
+      "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA=="
+    },
     "node_modules/@isaacs/cliui": {
       "version": "8.0.2",
       "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -1173,9 +1216,9 @@
       }
     },
     "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.4.15",
-      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
     },
     "node_modules/@jridgewell/trace-mapping": {
       "version": "0.3.25",
@@ -1243,6 +1286,12 @@
       "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==",
       "dev": true
     },
+    "node_modules/@popperjs/core": {
+      "name": "@sxzz/popperjs-es",
+      "version": "2.11.7",
+      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
+      "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
+    },
     "node_modules/@rollup/pluginutils": {
       "version": "5.1.0",
       "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
@@ -1836,6 +1885,29 @@
       "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==",
       "dev": true
     },
+    "node_modules/@vuepic/vue-datepicker": {
+      "version": "9.0.2",
+      "resolved": "https://registry.npmmirror.com/@vuepic/vue-datepicker/-/vue-datepicker-9.0.2.tgz",
+      "integrity": "sha512-VDAexzBJSvpErld1cZdGsBc+W/iU+Z+I98YNtEEboSSHUKHRi1s/h8s5D+wciZHLxgQ6P/tj6loNi4W7DgkYSQ==",
+      "dependencies": {
+        "date-fns": "^3.6.0"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      },
+      "peerDependencies": {
+        "vue": ">=3.2.0"
+      }
+    },
+    "node_modules/@vuepic/vue-datepicker/node_modules/date-fns": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/date-fns/-/date-fns-3.6.0.tgz",
+      "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/kossnocorp"
+      }
+    },
     "node_modules/@vueuse/core": {
       "version": "10.9.0",
       "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.9.0.tgz",
@@ -1869,6 +1941,18 @@
         "url": "https://github.com/sponsors/antfu"
       }
     },
+    "node_modules/acorn": {
+      "version": "8.12.1",
+      "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz",
+      "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
     "node_modules/ansi-regex": {
       "version": "2.1.1",
       "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz",
@@ -2530,6 +2614,12 @@
         "typedarray": "^0.0.6"
       }
     },
+    "node_modules/confbox": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.7.tgz",
+      "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==",
+      "dev": true
+    },
     "node_modules/convert-source-map": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -2821,8 +2911,7 @@
     "node_modules/dayjs": {
       "version": "1.11.11",
       "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz",
-      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==",
-      "dev": true
+      "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
     },
     "node_modules/de-indent": {
       "version": "1.0.2",
@@ -2831,9 +2920,9 @@
       "dev": true
     },
     "node_modules/debug": {
-      "version": "4.3.5",
-      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.5.tgz",
-      "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz",
+      "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -3069,6 +3158,69 @@
       "integrity": "sha512-rkg5/N3L+Y844JyfgPUyuKK0Hk0efo3JNxUDKvz3HgP6EmN4rNGhr2D8boLsfTV/hGo7ZGAL8djw+jlg99zQyA==",
       "dev": true
     },
+    "node_modules/element-plus": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.8.1.tgz",
+      "integrity": "sha512-p11/6w/O0+hGvPhiN3jrcgh+XG+eg5jZlLdQVYvcPHZYhhCh3J3YeZWW1JO/REPES1vevkboT6VAi+9wHA8Dsg==",
+      "dependencies": {
+        "@ctrl/tinycolor": "^3.4.1",
+        "@element-plus/icons-vue": "^2.3.1",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
+        "@types/lodash": "^4.14.182",
+        "@types/lodash-es": "^4.17.6",
+        "@vueuse/core": "^9.1.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.3",
+        "escape-html": "^1.0.3",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.21",
+        "lodash-unified": "^1.0.2",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/element-plus/node_modules/@types/web-bluetooth": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
+      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
+    },
+    "node_modules/element-plus/node_modules/@vueuse/core": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
+      "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.16",
+        "@vueuse/metadata": "9.13.0",
+        "@vueuse/shared": "9.13.0",
+        "vue-demi": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/element-plus/node_modules/@vueuse/metadata": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
+      "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/element-plus/node_modules/@vueuse/shared": {
+      "version": "9.13.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
+      "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
+      "dependencies": {
+        "vue-demi": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
     "node_modules/emoji-regex": {
       "version": "9.2.2",
       "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -3278,6 +3430,11 @@
         "node": ">=6"
       }
     },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+    },
     "node_modules/escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -4681,6 +4838,22 @@
         "node": ">=4.0.0"
       }
     },
+    "node_modules/local-pkg": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.0.tgz",
+      "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
+      "dev": true,
+      "dependencies": {
+        "mlly": "^1.4.2",
+        "pkg-types": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
     "node_modules/lodash": {
       "version": "4.17.21",
       "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
@@ -4691,6 +4864,16 @@
       "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
       "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
     },
+    "node_modules/lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "peerDependencies": {
+        "@types/lodash-es": "*",
+        "lodash": "*",
+        "lodash-es": "*"
+      }
+    },
     "node_modules/log-symbols": {
       "version": "6.0.0",
       "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-6.0.0.tgz",
@@ -4729,11 +4912,11 @@
       }
     },
     "node_modules/magic-string": {
-      "version": "0.30.10",
-      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz",
-      "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+      "version": "0.30.11",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz",
+      "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
       "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.4.15"
+        "@jridgewell/sourcemap-codec": "^1.5.0"
       }
     },
     "node_modules/map-cache": {
@@ -4802,6 +4985,11 @@
       "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz",
       "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
     },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+    },
     "node_modules/memorystream": {
       "version": "0.3.1",
       "resolved": "https://registry.npmmirror.com/memorystream/-/memorystream-0.3.1.tgz",
@@ -4967,9 +5155,9 @@
       }
     },
     "node_modules/minimatch": {
-      "version": "9.0.4",
-      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.4.tgz",
-      "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+      "version": "9.0.5",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
@@ -5030,6 +5218,24 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/mlly": {
+      "version": "1.7.1",
+      "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.1.tgz",
+      "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.11.3",
+        "pathe": "^1.1.2",
+        "pkg-types": "^1.1.1",
+        "ufo": "^1.5.3"
+      }
+    },
+    "node_modules/mlly/node_modules/pathe": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
+      "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+      "dev": true
+    },
     "node_modules/mrmime": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/mrmime/-/mrmime-2.0.0.tgz",
@@ -5225,6 +5431,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
+    },
     "node_modules/npm-normalize-package-bin": {
       "version": "3.0.1",
       "resolved": "https://registry.npmmirror.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
@@ -5696,6 +5907,23 @@
         "node": ">= 6"
       }
     },
+    "node_modules/pkg-types": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.2.0.tgz",
+      "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==",
+      "dev": true,
+      "dependencies": {
+        "confbox": "^0.1.7",
+        "mlly": "^1.7.1",
+        "pathe": "^1.1.2"
+      }
+    },
+    "node_modules/pkg-types/node_modules/pathe": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
+      "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+      "dev": true
+    },
     "node_modules/posix-character-classes": {
       "version": "0.1.1",
       "resolved": "https://registry.npmmirror.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -6438,6 +6666,12 @@
         }
       }
     },
+    "node_modules/scule": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
+      "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
+      "dev": true
+    },
     "node_modules/seemly": {
       "version": "0.3.8",
       "resolved": "https://registry.npmmirror.com/seemly/-/seemly-0.3.8.tgz",
@@ -7074,6 +7308,24 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/strip-literal": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-2.1.0.tgz",
+      "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==",
+      "dev": true,
+      "dependencies": {
+        "js-tokens": "^9.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/strip-literal/node_modules/js-tokens": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.0.tgz",
+      "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
+      "dev": true
+    },
     "node_modules/sucrase": {
       "version": "3.35.0",
       "resolved": "https://registry.npmmirror.com/sucrase/-/sucrase-3.35.0.tgz",
@@ -7305,6 +7557,14 @@
       "resolved": "https://registry.npmmirror.com/three/-/three-0.166.1.tgz",
       "integrity": "sha512-LtuafkKHHzm61AQA1be2MAYIw1IjmhOUxhBa0prrLpEMWbV7ijvxCRHjSgHPGp2493wLBzwKV46tA9nivLEgKg=="
     },
+    "node_modules/throttle-debounce": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.0.tgz",
+      "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==",
+      "engines": {
+        "node": ">=12.22"
+      }
+    },
     "node_modules/to-fast-properties": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -7575,6 +7835,12 @@
       "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz",
       "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
     },
+    "node_modules/ufo": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz",
+      "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
+      "dev": true
+    },
     "node_modules/unbox-primitive": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@@ -7596,6 +7862,54 @@
       "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
       "dev": true
     },
+    "node_modules/unimport": {
+      "version": "3.11.1",
+      "resolved": "https://registry.npmmirror.com/unimport/-/unimport-3.11.1.tgz",
+      "integrity": "sha512-DuB1Uoq01LrrXTScxnwOoMSlTXxyKcULguFxbLrMDFcE/CO0ZWHpEiyhovN0mycPt7K6luAHe8laqvwvuoeUPg==",
+      "dev": true,
+      "dependencies": {
+        "@rollup/pluginutils": "^5.1.0",
+        "acorn": "^8.12.1",
+        "escape-string-regexp": "^5.0.0",
+        "estree-walker": "^3.0.3",
+        "fast-glob": "^3.3.2",
+        "local-pkg": "^0.5.0",
+        "magic-string": "^0.30.11",
+        "mlly": "^1.7.1",
+        "pathe": "^1.1.2",
+        "pkg-types": "^1.2.0",
+        "scule": "^1.3.0",
+        "strip-literal": "^2.1.0",
+        "unplugin": "^1.12.2"
+      }
+    },
+    "node_modules/unimport/node_modules/escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/unimport/node_modules/estree-walker": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
+      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "^1.0.0"
+      }
+    },
+    "node_modules/unimport/node_modules/pathe": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
+      "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+      "dev": true
+    },
     "node_modules/union-value": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/union-value/-/union-value-1.0.1.tgz",
@@ -7620,6 +7934,92 @@
         "node": ">= 10.0.0"
       }
     },
+    "node_modules/unplugin": {
+      "version": "1.12.2",
+      "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-1.12.2.tgz",
+      "integrity": "sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.12.1",
+        "chokidar": "^3.6.0",
+        "webpack-sources": "^3.2.3",
+        "webpack-virtual-modules": "^0.6.2"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/unplugin-auto-import": {
+      "version": "0.18.2",
+      "resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.18.2.tgz",
+      "integrity": "sha512-Dwb3rAic75harVBrVjwiq6H24PT+nBq2dpxV5BH8NNI6sDFaTytvP+iyo4xy7prQbR3r5K6nMs4f5Wp9PE4g8A==",
+      "dev": true,
+      "dependencies": {
+        "@antfu/utils": "^0.7.10",
+        "@rollup/pluginutils": "^5.1.0",
+        "fast-glob": "^3.3.2",
+        "local-pkg": "^0.5.0",
+        "magic-string": "^0.30.10",
+        "minimatch": "^9.0.5",
+        "unimport": "^3.9.0",
+        "unplugin": "^1.11.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@nuxt/kit": "^3.2.2",
+        "@vueuse/core": "*"
+      },
+      "peerDependenciesMeta": {
+        "@nuxt/kit": {
+          "optional": true
+        },
+        "@vueuse/core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/unplugin-vue-components": {
+      "version": "0.27.4",
+      "resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.27.4.tgz",
+      "integrity": "sha512-1XVl5iXG7P1UrOMnaj2ogYa5YTq8aoh5jwDPQhemwO/OrXW+lPQKDXd1hMz15qxQPxgb/XXlbgo3HQ2rLEbmXQ==",
+      "dev": true,
+      "dependencies": {
+        "@antfu/utils": "^0.7.10",
+        "@rollup/pluginutils": "^5.1.0",
+        "chokidar": "^3.6.0",
+        "debug": "^4.3.6",
+        "fast-glob": "^3.3.2",
+        "local-pkg": "^0.5.0",
+        "magic-string": "^0.30.11",
+        "minimatch": "^9.0.5",
+        "mlly": "^1.7.1",
+        "unplugin": "^1.12.1"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@babel/parser": "^7.15.8",
+        "@nuxt/kit": "^3.2.2",
+        "vue": "2 || 3"
+      },
+      "peerDependenciesMeta": {
+        "@babel/parser": {
+          "optional": true
+        },
+        "@nuxt/kit": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/unset-value": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/unset-value/-/unset-value-1.0.0.tgz",
@@ -7999,6 +8399,14 @@
         "node": ">=10"
       }
     },
+    "node_modules/vue3-seamless-scroll": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/vue3-seamless-scroll/-/vue3-seamless-scroll-2.0.1.tgz",
+      "integrity": "sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==",
+      "dependencies": {
+        "throttle-debounce": "5.0.0"
+      }
+    },
     "node_modules/vueuc": {
       "version": "0.4.58",
       "resolved": "https://registry.npmmirror.com/vueuc/-/vueuc-0.4.58.tgz",
@@ -8016,6 +8424,21 @@
         "vue": "^3.0.11"
       }
     },
+    "node_modules/webpack-sources": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmmirror.com/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.6.2",
+      "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+      "dev": true
+    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",

+ 6 - 1
package.json

@@ -15,10 +15,12 @@
     "deploy:test": "node deploy/index.js --test"
   },
   "dependencies": {
+    "@vuepic/vue-datepicker": "^9.0.2",
     "@vueuse/core": "^10.9.0",
     "axios": "^1.6.8",
     "echarts": "^5.5.0",
     "echarts-gl": "^2.0.9",
+    "element-plus": "^2.8.1",
     "highlight.js": "^11.9.0",
     "katex": "^0.16.10",
     "load-awesome": "^1.1.0",
@@ -33,7 +35,8 @@
     "sass-loader": "^14.2.1",
     "three": "^0.166.1",
     "vue": "^3.4.21",
-    "vue-router": "^4.3.0"
+    "vue-router": "^4.3.0",
+    "vue3-seamless-scroll": "^2.0.1"
   },
   "devDependencies": {
     "@digitalacorn/vite-plugin-svg-icons": "^3.0.0-pre.1",
@@ -52,6 +55,8 @@
     "ssh2-sftp-client": "^10.0.3",
     "tailwindcss": "^3.4.4",
     "typescript": "~5.4.0",
+    "unplugin-auto-import": "^0.18.2",
+    "unplugin-vue-components": "^0.27.4",
     "vite": "^5.2.8",
     "vite-plugin-vue-devtools": "^7.0.25",
     "vue-tsc": "^2.0.11"

+ 2 - 3
src/App.vue

@@ -14,7 +14,6 @@ const themeOverrides: GlobalThemeOverrides = {
     primaryColorHover: '#2454FF',
     primaryColorPressed: '#2454FF',
     tableHeaderColor: '#F3F6F9',
-
   },
   Menu: {
     itemTextColor: primaryColor,
@@ -42,8 +41,8 @@ const themeOverrides: GlobalThemeOverrides = {
   },
   Input: {
     border: '0px',
-    borderHover: '0px ',
-    borderFocus: '0px ',
+    borderHover: '0px',
+    borderFocus: '0px',
     borderFocusWarning: '0px',
     boxShadowFocus: 'none',
     fontSizeMedium: '15px',

+ 26 - 0
src/api/carbon.js

@@ -0,0 +1,26 @@
+import http from "@/utils/request";
+
+export const carbonApi = {
+  /**
+   * 值集数据
+   */
+  getCodeSet: type => http.get(`system/dict/data/type/${ type }`),
+  
+  /**
+   * 碳源投加 基础数值数据
+   */
+  getAllMonth: () => http.get(`/front/bigModel/carbonSmart/allMonths`),
+
+  /**
+   * 新增核算数据
+   */
+  postCarbonSmart: data => http.post(`/front/bigModel/carbonSmart/addCarbonSmart`, data),
+
+  /**
+   * 详情数据
+   */
+  // /front/bigModel/carbonSmart/getCarbonDetailsByMonth/{id}
+  getDetails: data => http.get(`/front/bigModel/carbonSmart/getCarbonDetailsByMonth/${data}`, ),
+
+}
+

+ 8 - 0
src/api/env.js

@@ -0,0 +1,8 @@
+import http from "@/utils/request";
+
+export const envApi = {
+  /**
+   * 处理报警记录
+   */
+  handleWarnInfo: path => http.get(path),
+}

BIN
src/assets/fonts/YouSheBiaoTiHei.ttf


BIN
src/assets/images/carbon/Group 1321315504 (1).png


BIN
src/assets/images/carbon/Group 1321315573.png


BIN
src/assets/images/carbon/bg-3d.png


BIN
src/assets/images/carbon/bg-3d_副本.png


BIN
src/assets/images/carbon/bg-board-bottom.png


BIN
src/assets/images/carbon/bg-board-one.png


BIN
src/assets/images/carbon/bg-board-right.png


BIN
src/assets/images/carbon/bg-btn-1.png


BIN
src/assets/images/carbon/bg-btn-2.png


BIN
src/assets/images/carbon/bg-btn-3.png


BIN
src/assets/images/carbon/bg-btn-4.png


BIN
src/assets/images/carbon/bg-calendar-direction.png


BIN
src/assets/images/carbon/bg-calendar.png


BIN
src/assets/images/carbon/bg-footer.png


BIN
src/assets/images/carbon/bg-header.png


BIN
src/assets/images/carbon/bg-large-title.png


BIN
src/assets/images/carbon/bg-large-title1.png


BIN
src/assets/images/carbon/bg-screen-top.png


BIN
src/assets/images/carbon/bg-screen.png


BIN
src/assets/images/carbon/bg-title-data.png


BIN
src/assets/images/carbon/bg-title-energy.png


BIN
src/assets/images/carbon/bg-title-energy1.png


BIN
src/assets/images/carbon/bg-title-left-top.png


BIN
src/assets/images/carbon/bg-title-right-top.png


BIN
src/assets/images/carbon/bg-title.png


BIN
src/assets/images/carbon/bg.png


BIN
src/assets/images/carbon/icon-btn_back.png


BIN
src/assets/images/carbon/icon-up.png


+ 125 - 0
src/assets/images/carbon/svg/icon-borad-five.svg

@@ -0,0 +1,125 @@
+<svg width="79" height="79" viewBox="0 0 79 79" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.88003 54.9008L2.24578 55.2034L2.86798 55.5301L39.2994 74.6591L39.4628 74.7449L39.6263 74.6593L76.1572 55.5303L76.7794 55.2044L76.1459 54.901L39.7346 37.46L39.5828 37.3873L39.4309 37.4597L2.88003 54.9008Z" fill="#041F23" fill-opacity="0.43" stroke="#0E4047" stroke-width="0.704"/>
+<g clip-path="url(#clip0_2993_2338)">
+<path d="M39.3952 65.0004L69.0924 49.8988V52.4969L39.3952 68.248V65.0004Z" fill="url(#paint0_linear_2993_2338)"/>
+<path d="M39.3952 65.0004L9.86401 50.0612V52.6593L39.3952 68.2481V65.0004Z" fill="url(#paint1_linear_2993_2338)"/>
+<path d="M10.2476 49.7494L9.59213 50.0636L10.2451 50.383L39.2289 64.5605L39.3864 64.6375L39.5427 64.5583L67.8484 50.2165L68.4871 49.8929L67.8408 49.5847L39.2901 35.9721L39.1382 35.8997L38.9864 35.9724L10.2476 49.7494Z" fill="url(#paint2_linear_2993_2338)" stroke="url(#paint3_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<g clip-path="url(#clip1_2993_2338)">
+<path d="M39.4945 57.7276L63.2855 45.6118V47.6962L39.4945 60.3332V57.7276Z" fill="url(#paint4_linear_2993_2338)"/>
+<path d="M39.4945 57.7277L15.8365 45.7421V47.8265L39.4945 60.3332V57.7277Z" fill="url(#paint5_linear_2993_2338)"/>
+<path d="M16.1205 45.4286L15.4869 45.7323L16.1095 46.0579L39.008 58.0335L39.1716 58.1191L39.335 58.0332L62.3652 45.9258L62.987 45.5989L62.3529 45.2965L39.4639 34.3834L39.312 34.3109L39.1602 34.3837L16.1205 45.4286Z" fill="url(#paint6_linear_2993_2338)" stroke="url(#paint7_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<path d="M15.9957 45.3139L15.4845 45.5733V45V14.7506V14.5281L15.6854 14.4326L38.3127 3.68206L38.8151 3.44337L38.8158 3.99957L38.8515 33.4996L38.8518 33.716L38.6588 33.8139L15.9957 45.3139Z" fill="white" fill-opacity="0.1" stroke="url(#paint8_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M62.6282 45.3137L63.1398 45.5741V45L63.1398 15.3113V15.0925L62.9436 14.9957L40.0197 3.68434L39.512 3.43379V4V33.3358V33.5516L39.7044 33.6495L62.6282 45.3137Z" fill="white" fill-opacity="0.1" stroke="url(#paint9_linear_2993_2338)" stroke-width="0.704"/>
+<g clip-path="url(#clip2_2993_2338)">
+<path d="M39.5122 49.9101L56.9811 41.0828V42.6014L39.5122 51.8084V49.9101Z" fill="url(#paint10_linear_2993_2338)"/>
+<path d="M39.5122 49.91L22.1409 41.1777V42.6963L39.5122 51.8084V49.91Z" fill="url(#paint11_linear_2993_2338)"/>
+<path d="M22.2817 40.8655L21.6481 41.1692L22.2707 41.4948L39.0206 50.2548L39.1841 50.3403L39.3475 50.2544L56.1936 41.3981L56.8155 41.0712L56.1813 40.7688L39.4385 32.7861L39.2866 32.7136L39.1348 32.7864L22.2817 40.8655Z" fill="url(#paint12_linear_2993_2338)" stroke="url(#paint13_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<g clip-path="url(#clip3_2993_2338)">
+<path d="M48.2893 17.1039C48.0664 17.007 47.8143 17.036 47.6107 17.1669V17.1718H47.601C47.5961 17.1766 47.5816 17.1863 47.5622 17.196C47.5375 17.2115 47.505 17.2309 47.4653 17.2542L47.3925 17.2978C47.2423 17.3851 47.0241 17.5014 46.7575 17.6274C46.2194 17.8795 45.502 18.151 44.7507 18.2576C44.2698 18.325 43.6837 18.3206 43.0211 18.3158H43.0026C40.5983 18.2964 37.1483 18.2688 33.6741 21.5782C31.7845 23.3776 30.3438 26.7117 31.4588 30.499C36.2869 25.3398 41.4946 24.0751 41.4946 24.0751L41.4156 24.109C36.4246 25.9884 32.6319 30.2504 30.1887 34.9137C30.157 34.9733 30.134 35.0371 30.1204 35.1032C30.0515 35.4352 30.2236 35.793 30.5523 35.9268C30.9207 36.0819 31.3473 35.9074 31.5024 35.5341C31.903 34.5626 32.3576 33.6143 32.8641 32.6935C34.3348 33.5374 36.3441 34.012 38.3568 34.012C40.6594 34.012 43.1073 33.3818 44.8718 31.7919C47.7416 29.2081 48.682 25.6258 48.9244 22.7706C49.0455 21.3358 48.9971 20.056 48.9147 19.1399C48.8758 18.6739 48.8176 18.2097 48.7402 17.7486C48.7382 17.7341 48.7353 17.7195 48.7324 17.7074C48.7288 17.6939 48.7265 17.6801 48.7256 17.6662C48.7256 17.6662 48.7208 17.642 48.7208 17.6323C48.6771 17.3948 48.5123 17.196 48.2893 17.1039Z" fill="#6497BB"/>
+<path d="M47.1819 17.1039C46.9589 17.007 46.7069 17.036 46.5033 17.1669V17.1718H46.4936C46.4887 17.1766 46.4742 17.1863 46.4548 17.196C46.4301 17.2115 46.3976 17.2309 46.3578 17.2542L46.2851 17.2978C46.1349 17.3851 45.9167 17.5014 45.6501 17.6274C45.112 17.8795 44.3946 18.151 43.6432 18.2576C43.1624 18.325 42.5763 18.3206 41.9136 18.3158H41.8952C39.4909 18.2964 36.0409 18.2688 32.5667 21.5782C30.6771 23.3776 29.2364 26.7117 30.3514 30.499C35.1795 25.3398 40.3872 24.0751 40.3872 24.0751L40.3081 24.109C35.3171 25.9884 31.5245 30.2504 29.0813 34.9137C29.0496 34.9733 29.0266 35.0371 29.013 35.1032C28.9441 35.4352 29.1162 35.793 29.4449 35.9268C29.8133 36.0819 30.2399 35.9074 30.395 35.5341C30.7956 34.5626 31.2502 33.6143 31.7566 32.6935C33.2274 33.5374 35.2367 34.012 37.2494 34.012C39.5519 34.012 41.9999 33.3818 43.7644 31.7919C46.6341 29.2081 47.5746 25.6258 47.8169 22.7706C47.9381 21.3358 47.8897 20.056 47.8072 19.1399C47.7684 18.6739 47.7102 18.2097 47.6327 17.7486C47.6308 17.7341 47.6279 17.7195 47.625 17.7074C47.6214 17.6939 47.6191 17.6801 47.6182 17.6662C47.6182 17.6662 47.6133 17.642 47.6133 17.6323C47.5697 17.3948 47.4049 17.196 47.1819 17.1039Z" fill="white"/>
+</g>
+<path d="M62.6309 15.6849L63.1398 15.4314V16L63.1398 45.6768V45.8904L62.9504 45.9891L39.5577 58.1678L39.0431 58.4357V57.8556V27.6524V27.4345L39.2382 27.3373L62.6309 15.6849Z" fill="url(#paint14_linear_2993_2338)" stroke="url(#paint15_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M15.999 15.1615L15.4845 14.8936V15.4737V45.6768V45.8904L15.6739 45.9891L39.0666 58.1678L39.5812 58.4357V57.8556V27.6524V27.4388L39.3917 27.3402L15.999 15.1615Z" fill="url(#paint16_linear_2993_2338)" stroke="url(#paint17_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M46.7508 43.5091C55.5959 38.559 62.8207 32.6455 67.348 27.074C69.6109 24.2891 71.2117 21.575 71.9958 19.0967C72.7801 16.6175 72.7559 14.3405 71.7127 12.4765C70.6695 10.6125 68.7415 9.40116 66.2181 8.77308C63.6957 8.1452 60.5452 8.09024 56.988 8.56255C49.8715 9.50746 41.0527 12.5729 32.2076 17.5231C23.3625 22.4732 16.1376 28.3867 11.6104 33.9582C9.34748 36.7431 7.74665 39.4572 6.96261 41.9355C6.17831 44.4147 6.20244 46.6917 7.24563 48.5557C8.28883 50.4197 10.2169 51.631 12.7402 52.2591C15.2627 52.887 18.4132 52.942 21.9704 52.4697C29.0869 51.5247 37.9057 48.4593 46.7508 43.5091Z" stroke="url(#paint18_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M70.6613 23.8467C71.5051 23.8467 72.1901 23.1637 72.1901 22.3199C72.1901 21.4762 71.5051 20.7932 70.6613 20.7932C69.8176 20.7932 69.1326 21.4762 69.1326 22.3199C69.1326 23.1637 69.8176 23.8467 70.6613 23.8467Z" fill="#B5E8FF" stroke="white" stroke-width="0.704"/>
+<path d="M34.1829 71.6588L39.8704 74.5957L45.3617 71.6588" stroke="#B5E8FF" stroke-width="0.704"/>
+<path d="M73.0148 53.2546L77.3294 55.4083L73.0148 57.562" stroke="#B5E8FF" stroke-width="0.704"/>
+<defs>
+<linearGradient id="paint0_linear_2993_2338" x1="56.6091" y1="42.1856" x2="38.8325" y2="66.373" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2993_2338" x1="22.2776" y1="42.4163" x2="39.8794" y2="66.4449" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2993_2338" x1="25.5302" y1="37.6182" x2="25.9259" y2="63.63" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2993_2338" x1="24.5578" y1="36.2378" x2="24.642" y2="65.2105" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2993_2338" x1="53.2849" y1="39.4235" x2="39.0167" y2="58.809" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2993_2338" x1="25.7812" y1="39.6086" x2="39.9093" y2="58.8669" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint6_linear_2993_2338" x1="28.4027" y1="35.766" x2="28.7199" y2="56.6196" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint7_linear_2993_2338" x1="27.6231" y1="34.6594" x2="27.6906" y2="57.8866" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint8_linear_2993_2338" x1="11.848" y1="10.6834" x2="37.0675" y2="5.93679" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint9_linear_2993_2338" x1="66.7762" y1="10.6834" x2="41.5568" y2="5.9368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint10_linear_2993_2338" x1="49.638" y1="36.5742" x2="39.2669" y2="50.775" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint11_linear_2993_2338" x1="29.443" y1="36.709" x2="39.712" y2="50.8163" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint12_linear_2993_2338" x1="31.3067" y1="33.8828" x2="31.5388" y2="49.1368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint13_linear_2993_2338" x1="30.7365" y1="33.0733" x2="30.7858" y2="50.0636" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint14_linear_2993_2338" x1="56.3327" y1="28.4493" x2="63.1934" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint15_linear_2993_2338" x1="66.7763" y1="50.3048" x2="41.5568" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint16_linear_2993_2338" x1="22.2916" y1="28.4493" x2="15.4309" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint17_linear_2993_2338" x1="11.848" y1="50.3048" x2="37.0675" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint18_linear_2993_2338" x1="0.453125" y1="35.6979" x2="14.6525" y2="61.0696" gradientUnits="userSpaceOnUse">
+<stop stop-opacity="0.01"/>
+<stop offset="0.490635" stop-color="#B5EFFF"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<clipPath id="clip0_2993_2338">
+<rect width="59.2284" height="56.6714" fill="white" transform="translate(9.86401 21.6442)"/>
+</clipPath>
+<clipPath id="clip1_2993_2338">
+<rect width="47.4491" height="45.4671" fill="white" transform="translate(15.8365 22.9433)"/>
+</clipPath>
+<clipPath id="clip2_2993_2338">
+<rect width="34.8402" height="33.126" fill="white" transform="translate(22.1409 24.5671)"/>
+</clipPath>
+<clipPath id="clip3_2993_2338">
+<rect width="21" height="21" fill="white" transform="translate(28.9998 16)"/>
+</clipPath>
+</defs>
+</svg>

+ 120 - 0
src/assets/images/carbon/svg/icon-borad-four.svg

@@ -0,0 +1,120 @@
+<svg width="79" height="79" viewBox="0 0 79 79" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.88003 54.9008L2.24578 55.2034L2.86798 55.5301L39.2994 74.6591L39.4628 74.7449L39.6263 74.6593L76.1572 55.5303L76.7794 55.2044L76.1459 54.901L39.7346 37.46L39.5828 37.3873L39.4309 37.4597L2.88003 54.9008Z" fill="#041F23" fill-opacity="0.43" stroke="#0E4047" stroke-width="0.704"/>
+<g clip-path="url(#clip0_2993_2178)">
+<path d="M39.3953 65.0004L69.0924 49.8988V52.4969L39.3953 68.248V65.0004Z" fill="url(#paint0_linear_2993_2178)"/>
+<path d="M39.3953 65.0004L9.86403 50.0612V52.6593L39.3953 68.2481V65.0004Z" fill="url(#paint1_linear_2993_2178)"/>
+<path d="M10.2476 49.7494L9.59213 50.0636L10.2451 50.383L39.2289 64.5605L39.3864 64.6375L39.5427 64.5583L67.8484 50.2165L68.4871 49.8929L67.8408 49.5847L39.2901 35.9721L39.1382 35.8997L38.9864 35.9724L10.2476 49.7494Z" fill="url(#paint2_linear_2993_2178)" stroke="url(#paint3_linear_2993_2178)" stroke-width="0.704"/>
+</g>
+<g clip-path="url(#clip1_2993_2178)">
+<path d="M39.4945 57.7276L63.2855 45.6118V47.6962L39.4945 60.3332V57.7276Z" fill="url(#paint4_linear_2993_2178)"/>
+<path d="M39.4945 57.7277L15.8365 45.7421V47.8265L39.4945 60.3332V57.7277Z" fill="url(#paint5_linear_2993_2178)"/>
+<path d="M16.1205 45.4286L15.4869 45.7323L16.1095 46.0579L39.0081 58.0335L39.1716 58.1191L39.335 58.0332L62.3652 45.9258L62.987 45.5989L62.3529 45.2965L39.4639 34.3834L39.312 34.3109L39.1602 34.3837L16.1205 45.4286Z" fill="url(#paint6_linear_2993_2178)" stroke="url(#paint7_linear_2993_2178)" stroke-width="0.704"/>
+</g>
+<path d="M15.9957 45.3139L15.4845 45.5733V45V14.7506V14.5281L15.6854 14.4326L38.3127 3.68206L38.8151 3.44337L38.8158 3.99957L38.8515 33.4996L38.8518 33.716L38.6588 33.8139L15.9957 45.3139Z" fill="white" fill-opacity="0.1" stroke="url(#paint8_linear_2993_2178)" stroke-width="0.704"/>
+<path d="M62.6282 45.3137L63.1398 45.5741V45L63.1398 15.3113V15.0925L62.9436 14.9957L40.0197 3.68434L39.512 3.43379V4V33.3358V33.5516L39.7044 33.6495L62.6282 45.3137Z" fill="white" fill-opacity="0.1" stroke="url(#paint9_linear_2993_2178)" stroke-width="0.704"/>
+<g clip-path="url(#clip2_2993_2178)">
+<path d="M39.5122 49.9101L56.9811 41.0828V42.6014L39.5122 51.8084V49.9101Z" fill="url(#paint10_linear_2993_2178)"/>
+<path d="M39.5122 49.91L22.1409 41.1777V42.6963L39.5122 51.8084V49.91Z" fill="url(#paint11_linear_2993_2178)"/>
+<path d="M22.2817 40.8655L21.6481 41.1692L22.2707 41.4948L39.0206 50.2548L39.1841 50.3403L39.3475 50.2544L56.1936 41.3981L56.8155 41.0712L56.1813 40.7688L39.4385 32.7861L39.2866 32.7136L39.1348 32.7864L22.2817 40.8655Z" fill="url(#paint12_linear_2993_2178)" stroke="url(#paint13_linear_2993_2178)" stroke-width="0.704"/>
+</g>
+<path d="M39.3242 35.5C39.207 35.4999 39.0919 35.469 38.9904 35.4106L31.3465 30.9951C31.2452 30.9362 31.1611 30.8519 31.1025 30.7504C31.0439 30.649 31.0129 30.5339 31.0126 30.4168V21.585C31.0126 21.4754 31.0126 21.3711 32.056 20.6989C33.1433 19.9991 35.2821 18.7322 38.9866 16.5904C39.0885 16.5312 39.2042 16.5 39.322 16.5C39.4398 16.5 39.5555 16.5312 39.6573 16.5904L47.3027 21.0067C47.404 21.0655 47.4881 21.1499 47.5467 21.2513C47.6053 21.3528 47.6363 21.4678 47.6366 21.585V30.4168C47.6363 30.5339 47.6053 30.649 47.5467 30.7504C47.4881 30.8519 47.404 30.9362 47.3027 30.9951L39.6573 35.4106C39.556 35.4689 39.4412 35.4997 39.3242 35.5ZM40.6895 19.5147C40.6605 19.518 40.6328 19.5284 40.6088 19.545C40.5849 19.5617 40.5655 19.5841 40.5524 19.6101L35.0153 26.8508C34.9824 26.8806 34.9616 26.9213 34.9566 26.9654C34.9517 27.0094 34.963 27.0537 34.9885 27.09C35.0053 27.1244 35.0321 27.1529 35.0653 27.1719C35.0985 27.1909 35.1366 27.1995 35.1748 27.1966H38.769L37.9433 32.0689C37.9347 32.0887 37.9302 32.11 37.9302 32.1315C37.9302 32.1531 37.9347 32.1744 37.9433 32.1941C37.9582 32.2168 37.9774 32.2363 38 32.2514C38.0225 32.2665 38.0478 32.2769 38.0745 32.2821C38.0965 32.3012 38.1251 32.3109 38.1542 32.3089C38.1891 32.309 38.2235 32.3019 38.2556 32.2882C38.2876 32.2745 38.3165 32.2544 38.3405 32.2292L43.458 24.9877C43.4755 24.9089 43.4755 24.8273 43.458 24.7485C43.4411 24.7142 43.4143 24.6858 43.3811 24.6668C43.348 24.6478 43.3099 24.6392 43.2717 24.6419H40.1L40.9242 19.7704C40.9242 19.6466 40.8795 19.5751 40.7908 19.5572C40.763 19.5322 40.7276 19.5173 40.6902 19.5147H40.6895Z" fill="#6497BB"/>
+<path d="M38.6113 35.5C38.4941 35.4999 38.379 35.469 38.2775 35.4106L30.6336 30.9951C30.5323 30.9362 30.4482 30.8519 30.3896 30.7504C30.331 30.649 30.3 30.5339 30.2997 30.4168V21.585C30.2997 21.4754 30.2997 21.3711 31.3431 20.6989C32.4304 19.9991 34.5692 18.7322 38.2737 16.5904C38.3756 16.5312 38.4913 16.5 38.6091 16.5C38.7269 16.5 38.8426 16.5312 38.9445 16.5904L46.5898 21.0067C46.6911 21.0655 46.7752 21.1499 46.8338 21.2513C46.8924 21.3528 46.9234 21.4678 46.9237 21.585V30.4168C46.9234 30.5339 46.8924 30.649 46.8338 30.7504C46.7752 30.8519 46.6911 30.9362 46.5898 30.9951L38.9445 35.4106C38.8431 35.4689 38.7283 35.4997 38.6113 35.5ZM39.9766 19.5147C39.9476 19.518 39.9199 19.5284 39.8959 19.545C39.872 19.5617 39.8526 19.5841 39.8395 19.6101L34.3024 26.8508C34.2695 26.8806 34.2487 26.9213 34.2437 26.9654C34.2388 27.0094 34.2501 27.0537 34.2756 27.09C34.2924 27.1244 34.3192 27.1529 34.3524 27.1719C34.3856 27.1909 34.4237 27.1995 34.4619 27.1966H38.0561L37.2304 32.0689C37.2218 32.0887 37.2174 32.11 37.2174 32.1315C37.2174 32.1531 37.2218 32.1744 37.2304 32.1941C37.2453 32.2168 37.2646 32.2363 37.2871 32.2514C37.3096 32.2665 37.3349 32.2769 37.3616 32.2821C37.3836 32.3012 37.4122 32.3109 37.4413 32.3089C37.4762 32.309 37.5107 32.3019 37.5427 32.2882C37.5747 32.2745 37.6036 32.2544 37.6276 32.2292L42.7451 24.9877C42.7626 24.9089 42.7626 24.8273 42.7451 24.7485C42.7282 24.7142 42.7014 24.6858 42.6682 24.6668C42.6351 24.6478 42.597 24.6392 42.5588 24.6419H39.3871L40.2114 19.7704C40.2114 19.6466 40.1666 19.5751 40.078 19.5572C40.0501 19.5322 40.0147 19.5173 39.9773 19.5147H39.9766Z" fill="white"/>
+<path d="M62.6309 15.6849L63.1398 15.4314V16L63.1398 45.6768V45.8904L62.9504 45.9891L39.5577 58.1678L39.0431 58.4357V57.8556V27.6524V27.4345L39.2382 27.3373L62.6309 15.6849Z" fill="url(#paint14_linear_2993_2178)" stroke="url(#paint15_linear_2993_2178)" stroke-width="0.704"/>
+<path d="M15.999 15.1615L15.4845 14.8936V15.4737V45.6768V45.8904L15.6739 45.9891L39.0666 58.1678L39.5812 58.4357V57.8556V27.6524V27.4388L39.3917 27.3402L15.999 15.1615Z" fill="url(#paint16_linear_2993_2178)" stroke="url(#paint17_linear_2993_2178)" stroke-width="0.704"/>
+<path d="M46.7508 43.5091C55.5959 38.559 62.8207 32.6455 67.348 27.074C69.6109 24.2891 71.2117 21.575 71.9958 19.0967C72.7801 16.6175 72.7559 14.3405 71.7127 12.4765C70.6695 10.6125 68.7415 9.40116 66.2181 8.77308C63.6957 8.1452 60.5452 8.09024 56.988 8.56255C49.8715 9.50746 41.0527 12.5729 32.2076 17.5231C23.3625 22.4732 16.1376 28.3867 11.6104 33.9582C9.34748 36.7431 7.74665 39.4572 6.96261 41.9355C6.17831 44.4147 6.20244 46.6917 7.24563 48.5557C8.28883 50.4197 10.2169 51.631 12.7402 52.2591C15.2627 52.887 18.4132 52.942 21.9704 52.4697C29.0869 51.5247 37.9057 48.4593 46.7508 43.5091Z" stroke="url(#paint18_linear_2993_2178)" stroke-width="0.704"/>
+<path d="M70.6613 23.8467C71.5051 23.8467 72.1901 23.1637 72.1901 22.3199C72.1901 21.4762 71.5051 20.7932 70.6613 20.7932C69.8176 20.7932 69.1326 21.4762 69.1326 22.3199C69.1326 23.1637 69.8176 23.8467 70.6613 23.8467Z" fill="#B5E8FF" stroke="white" stroke-width="0.704"/>
+<path d="M34.1829 71.6588L39.8704 74.5957L45.3617 71.6588" stroke="#B5E8FF" stroke-width="0.704"/>
+<path d="M73.0148 53.2546L77.3294 55.4083L73.0148 57.562" stroke="#B5E8FF" stroke-width="0.704"/>
+<defs>
+<linearGradient id="paint0_linear_2993_2178" x1="56.6091" y1="42.1856" x2="38.8326" y2="66.373" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2993_2178" x1="22.2776" y1="42.4163" x2="39.8794" y2="66.4449" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2993_2178" x1="25.5302" y1="37.6182" x2="25.9259" y2="63.63" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2993_2178" x1="24.5578" y1="36.2378" x2="24.642" y2="65.2105" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2993_2178" x1="53.2849" y1="39.4235" x2="39.0167" y2="58.809" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2993_2178" x1="25.7812" y1="39.6086" x2="39.9093" y2="58.8669" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint6_linear_2993_2178" x1="28.4027" y1="35.766" x2="28.7199" y2="56.6196" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint7_linear_2993_2178" x1="27.6231" y1="34.6594" x2="27.6906" y2="57.8866" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint8_linear_2993_2178" x1="11.848" y1="10.6834" x2="37.0675" y2="5.93679" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint9_linear_2993_2178" x1="66.7762" y1="10.6834" x2="41.5568" y2="5.9368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint10_linear_2993_2178" x1="49.638" y1="36.5742" x2="39.2669" y2="50.775" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint11_linear_2993_2178" x1="29.443" y1="36.709" x2="39.7119" y2="50.8163" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint12_linear_2993_2178" x1="31.3067" y1="33.8828" x2="31.5388" y2="49.1368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint13_linear_2993_2178" x1="30.7365" y1="33.0733" x2="30.7858" y2="50.0636" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint14_linear_2993_2178" x1="56.3327" y1="28.4493" x2="63.1934" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint15_linear_2993_2178" x1="66.7763" y1="50.3048" x2="41.5568" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint16_linear_2993_2178" x1="22.2916" y1="28.4493" x2="15.4309" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint17_linear_2993_2178" x1="11.848" y1="50.3048" x2="37.0675" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint18_linear_2993_2178" x1="0.453125" y1="35.6979" x2="14.6525" y2="61.0696" gradientUnits="userSpaceOnUse">
+<stop stop-opacity="0.01"/>
+<stop offset="0.490635" stop-color="#B5EFFF"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<clipPath id="clip0_2993_2178">
+<rect width="59.2284" height="56.6714" fill="white" transform="translate(9.86401 21.6442)"/>
+</clipPath>
+<clipPath id="clip1_2993_2178">
+<rect width="47.4491" height="45.4671" fill="white" transform="translate(15.8365 22.9433)"/>
+</clipPath>
+<clipPath id="clip2_2993_2178">
+<rect width="34.8402" height="33.126" fill="white" transform="translate(22.1409 24.5671)"/>
+</clipPath>
+</defs>
+</svg>

+ 125 - 0
src/assets/images/carbon/svg/icon-borad-one.svg

@@ -0,0 +1,125 @@
+<svg width="79" height="79" viewBox="0 0 79 79" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.88003 54.9008L2.24578 55.2034L2.86798 55.5301L39.2994 74.6591L39.4628 74.7449L39.6263 74.6593L76.1572 55.5303L76.7794 55.2044L76.1459 54.901L39.7346 37.46L39.5828 37.3873L39.4309 37.4597L2.88003 54.9008Z" fill="#041F23" fill-opacity="0.43" stroke="#0E4047" stroke-width="0.704"/>
+<g clip-path="url(#clip0_2993_2338)">
+<path d="M39.3952 65.0004L69.0924 49.8988V52.4969L39.3952 68.248V65.0004Z" fill="url(#paint0_linear_2993_2338)"/>
+<path d="M39.3952 65.0004L9.86401 50.0612V52.6593L39.3952 68.2481V65.0004Z" fill="url(#paint1_linear_2993_2338)"/>
+<path d="M10.2476 49.7494L9.59213 50.0636L10.2451 50.383L39.2289 64.5605L39.3864 64.6375L39.5427 64.5583L67.8484 50.2165L68.4871 49.8929L67.8408 49.5847L39.2901 35.9721L39.1382 35.8997L38.9864 35.9724L10.2476 49.7494Z" fill="url(#paint2_linear_2993_2338)" stroke="url(#paint3_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<g clip-path="url(#clip1_2993_2338)">
+<path d="M39.4945 57.7276L63.2855 45.6118V47.6962L39.4945 60.3332V57.7276Z" fill="url(#paint4_linear_2993_2338)"/>
+<path d="M39.4945 57.7277L15.8365 45.7421V47.8265L39.4945 60.3332V57.7277Z" fill="url(#paint5_linear_2993_2338)"/>
+<path d="M16.1205 45.4286L15.4869 45.7323L16.1095 46.0579L39.008 58.0335L39.1716 58.1191L39.335 58.0332L62.3652 45.9258L62.987 45.5989L62.3529 45.2965L39.4639 34.3834L39.312 34.3109L39.1602 34.3837L16.1205 45.4286Z" fill="url(#paint6_linear_2993_2338)" stroke="url(#paint7_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<path d="M15.9957 45.3139L15.4845 45.5733V45V14.7506V14.5281L15.6854 14.4326L38.3127 3.68206L38.8151 3.44337L38.8158 3.99957L38.8515 33.4996L38.8518 33.716L38.6588 33.8139L15.9957 45.3139Z" fill="white" fill-opacity="0.1" stroke="url(#paint8_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M62.6282 45.3137L63.1398 45.5741V45L63.1398 15.3113V15.0925L62.9436 14.9957L40.0197 3.68434L39.512 3.43379V4V33.3358V33.5516L39.7044 33.6495L62.6282 45.3137Z" fill="white" fill-opacity="0.1" stroke="url(#paint9_linear_2993_2338)" stroke-width="0.704"/>
+<g clip-path="url(#clip2_2993_2338)">
+<path d="M39.5122 49.9101L56.9811 41.0828V42.6014L39.5122 51.8084V49.9101Z" fill="url(#paint10_linear_2993_2338)"/>
+<path d="M39.5122 49.91L22.1409 41.1777V42.6963L39.5122 51.8084V49.91Z" fill="url(#paint11_linear_2993_2338)"/>
+<path d="M22.2817 40.8655L21.6481 41.1692L22.2707 41.4948L39.0206 50.2548L39.1841 50.3403L39.3475 50.2544L56.1936 41.3981L56.8155 41.0712L56.1813 40.7688L39.4385 32.7861L39.2866 32.7136L39.1348 32.7864L22.2817 40.8655Z" fill="url(#paint12_linear_2993_2338)" stroke="url(#paint13_linear_2993_2338)" stroke-width="0.704"/>
+</g>
+<g clip-path="url(#clip3_2993_2338)">
+<path d="M48.2893 17.1039C48.0664 17.007 47.8143 17.036 47.6107 17.1669V17.1718H47.601C47.5961 17.1766 47.5816 17.1863 47.5622 17.196C47.5375 17.2115 47.505 17.2309 47.4653 17.2542L47.3925 17.2978C47.2423 17.3851 47.0241 17.5014 46.7575 17.6274C46.2194 17.8795 45.502 18.151 44.7507 18.2576C44.2698 18.325 43.6837 18.3206 43.0211 18.3158H43.0026C40.5983 18.2964 37.1483 18.2688 33.6741 21.5782C31.7845 23.3776 30.3438 26.7117 31.4588 30.499C36.2869 25.3398 41.4946 24.0751 41.4946 24.0751L41.4156 24.109C36.4246 25.9884 32.6319 30.2504 30.1887 34.9137C30.157 34.9733 30.134 35.0371 30.1204 35.1032C30.0515 35.4352 30.2236 35.793 30.5523 35.9268C30.9207 36.0819 31.3473 35.9074 31.5024 35.5341C31.903 34.5626 32.3576 33.6143 32.8641 32.6935C34.3348 33.5374 36.3441 34.012 38.3568 34.012C40.6594 34.012 43.1073 33.3818 44.8718 31.7919C47.7416 29.2081 48.682 25.6258 48.9244 22.7706C49.0455 21.3358 48.9971 20.056 48.9147 19.1399C48.8758 18.6739 48.8176 18.2097 48.7402 17.7486C48.7382 17.7341 48.7353 17.7195 48.7324 17.7074C48.7288 17.6939 48.7265 17.6801 48.7256 17.6662C48.7256 17.6662 48.7208 17.642 48.7208 17.6323C48.6771 17.3948 48.5123 17.196 48.2893 17.1039Z" fill="#6497BB"/>
+<path d="M47.1819 17.1039C46.9589 17.007 46.7069 17.036 46.5033 17.1669V17.1718H46.4936C46.4887 17.1766 46.4742 17.1863 46.4548 17.196C46.4301 17.2115 46.3976 17.2309 46.3578 17.2542L46.2851 17.2978C46.1349 17.3851 45.9167 17.5014 45.6501 17.6274C45.112 17.8795 44.3946 18.151 43.6432 18.2576C43.1624 18.325 42.5763 18.3206 41.9136 18.3158H41.8952C39.4909 18.2964 36.0409 18.2688 32.5667 21.5782C30.6771 23.3776 29.2364 26.7117 30.3514 30.499C35.1795 25.3398 40.3872 24.0751 40.3872 24.0751L40.3081 24.109C35.3171 25.9884 31.5245 30.2504 29.0813 34.9137C29.0496 34.9733 29.0266 35.0371 29.013 35.1032C28.9441 35.4352 29.1162 35.793 29.4449 35.9268C29.8133 36.0819 30.2399 35.9074 30.395 35.5341C30.7956 34.5626 31.2502 33.6143 31.7566 32.6935C33.2274 33.5374 35.2367 34.012 37.2494 34.012C39.5519 34.012 41.9999 33.3818 43.7644 31.7919C46.6341 29.2081 47.5746 25.6258 47.8169 22.7706C47.9381 21.3358 47.8897 20.056 47.8072 19.1399C47.7684 18.6739 47.7102 18.2097 47.6327 17.7486C47.6308 17.7341 47.6279 17.7195 47.625 17.7074C47.6214 17.6939 47.6191 17.6801 47.6182 17.6662C47.6182 17.6662 47.6133 17.642 47.6133 17.6323C47.5697 17.3948 47.4049 17.196 47.1819 17.1039Z" fill="white"/>
+</g>
+<path d="M62.6309 15.6849L63.1398 15.4314V16L63.1398 45.6768V45.8904L62.9504 45.9891L39.5577 58.1678L39.0431 58.4357V57.8556V27.6524V27.4345L39.2382 27.3373L62.6309 15.6849Z" fill="url(#paint14_linear_2993_2338)" stroke="url(#paint15_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M15.999 15.1615L15.4845 14.8936V15.4737V45.6768V45.8904L15.6739 45.9891L39.0666 58.1678L39.5812 58.4357V57.8556V27.6524V27.4388L39.3917 27.3402L15.999 15.1615Z" fill="url(#paint16_linear_2993_2338)" stroke="url(#paint17_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M46.7508 43.5091C55.5959 38.559 62.8207 32.6455 67.348 27.074C69.6109 24.2891 71.2117 21.575 71.9958 19.0967C72.7801 16.6175 72.7559 14.3405 71.7127 12.4765C70.6695 10.6125 68.7415 9.40116 66.2181 8.77308C63.6957 8.1452 60.5452 8.09024 56.988 8.56255C49.8715 9.50746 41.0527 12.5729 32.2076 17.5231C23.3625 22.4732 16.1376 28.3867 11.6104 33.9582C9.34748 36.7431 7.74665 39.4572 6.96261 41.9355C6.17831 44.4147 6.20244 46.6917 7.24563 48.5557C8.28883 50.4197 10.2169 51.631 12.7402 52.2591C15.2627 52.887 18.4132 52.942 21.9704 52.4697C29.0869 51.5247 37.9057 48.4593 46.7508 43.5091Z" stroke="url(#paint18_linear_2993_2338)" stroke-width="0.704"/>
+<path d="M70.6613 23.8467C71.5051 23.8467 72.1901 23.1637 72.1901 22.3199C72.1901 21.4762 71.5051 20.7932 70.6613 20.7932C69.8176 20.7932 69.1326 21.4762 69.1326 22.3199C69.1326 23.1637 69.8176 23.8467 70.6613 23.8467Z" fill="#B5E8FF" stroke="white" stroke-width="0.704"/>
+<path d="M34.1829 71.6588L39.8704 74.5957L45.3617 71.6588" stroke="#B5E8FF" stroke-width="0.704"/>
+<path d="M73.0148 53.2546L77.3294 55.4083L73.0148 57.562" stroke="#B5E8FF" stroke-width="0.704"/>
+<defs>
+<linearGradient id="paint0_linear_2993_2338" x1="56.6091" y1="42.1856" x2="38.8325" y2="66.373" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint1_linear_2993_2338" x1="22.2776" y1="42.4163" x2="39.8794" y2="66.4449" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint2_linear_2993_2338" x1="25.5302" y1="37.6182" x2="25.9259" y2="63.63" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint3_linear_2993_2338" x1="24.5578" y1="36.2378" x2="24.642" y2="65.2105" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint4_linear_2993_2338" x1="53.2849" y1="39.4235" x2="39.0167" y2="58.809" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint5_linear_2993_2338" x1="25.7812" y1="39.6086" x2="39.9093" y2="58.8669" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint6_linear_2993_2338" x1="28.4027" y1="35.766" x2="28.7199" y2="56.6196" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint7_linear_2993_2338" x1="27.6231" y1="34.6594" x2="27.6906" y2="57.8866" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint8_linear_2993_2338" x1="11.848" y1="10.6834" x2="37.0675" y2="5.93679" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint9_linear_2993_2338" x1="66.7762" y1="10.6834" x2="41.5568" y2="5.9368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint10_linear_2993_2338" x1="49.638" y1="36.5742" x2="39.2669" y2="50.775" gradientUnits="userSpaceOnUse">
+<stop stop-color="#2A93C4"/>
+<stop offset="1" stop-color="#0D2C3A"/>
+</linearGradient>
+<linearGradient id="paint11_linear_2993_2338" x1="29.443" y1="36.709" x2="39.712" y2="50.8163" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0D2C3A"/>
+<stop offset="1" stop-color="#2A93C4"/>
+</linearGradient>
+<linearGradient id="paint12_linear_2993_2338" x1="31.3067" y1="33.8828" x2="31.5388" y2="49.1368" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34ADBF"/>
+<stop offset="1" stop-color="#094883"/>
+</linearGradient>
+<linearGradient id="paint13_linear_2993_2338" x1="30.7365" y1="33.0733" x2="30.7858" y2="50.0636" gradientUnits="userSpaceOnUse">
+<stop stop-color="#0E4047"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<linearGradient id="paint14_linear_2993_2338" x1="56.3327" y1="28.4493" x2="63.1934" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint15_linear_2993_2338" x1="66.7763" y1="50.3048" x2="41.5568" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint16_linear_2993_2338" x1="22.2916" y1="28.4493" x2="15.4309" y2="45.6235" gradientUnits="userSpaceOnUse">
+<stop stop-color="#48C0F7" stop-opacity="0.14"/>
+<stop offset="1" stop-color="white" stop-opacity="0.41"/>
+</linearGradient>
+<linearGradient id="paint17_linear_2993_2338" x1="11.848" y1="50.3048" x2="37.0675" y2="55.0514" gradientUnits="userSpaceOnUse">
+<stop stop-color="#82B5C5"/>
+<stop offset="0.474786" stop-color="#E3F7FD"/>
+<stop offset="1" stop-color="white" stop-opacity="0.37"/>
+</linearGradient>
+<linearGradient id="paint18_linear_2993_2338" x1="0.453125" y1="35.6979" x2="14.6525" y2="61.0696" gradientUnits="userSpaceOnUse">
+<stop stop-opacity="0.01"/>
+<stop offset="0.490635" stop-color="#B5EFFF"/>
+<stop offset="1" stop-color="#B5EFFF"/>
+</linearGradient>
+<clipPath id="clip0_2993_2338">
+<rect width="59.2284" height="56.6714" fill="white" transform="translate(9.86401 21.6442)"/>
+</clipPath>
+<clipPath id="clip1_2993_2338">
+<rect width="47.4491" height="45.4671" fill="white" transform="translate(15.8365 22.9433)"/>
+</clipPath>
+<clipPath id="clip2_2993_2338">
+<rect width="34.8402" height="33.126" fill="white" transform="translate(22.1409 24.5671)"/>
+</clipPath>
+<clipPath id="clip3_2993_2338">
+<rect width="21" height="21" fill="white" transform="translate(28.9998 16)"/>
+</clipPath>
+</defs>
+</svg>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 19 - 0
src/assets/images/carbon/svg/icon-borad-six.svg


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 19 - 0
src/assets/images/carbon/svg/icon-borad-three.svg


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 20 - 0
src/assets/images/carbon/svg/icon-borad-two.svg


+ 3 - 0
src/assets/images/carbon/svg/icon-bottom-left.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
+  <path d="M18 17H11C5.47715 17 1 12.5228 1 7V-2.98023e-08" stroke="#75C4FF" stroke-width="2"/>
+</svg>

+ 3 - 0
src/assets/images/carbon/svg/icon-bottom-right.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none">
+  <path d="M0 17L7 17C12.5228 17 17 12.5228 17 7L17 -2.98023e-08" stroke="#75C4FF" stroke-width="2"/>
+</svg>

+ 3 - 0
src/assets/images/carbon/svg/icon-down.svg

@@ -0,0 +1,3 @@
+<svg width="14" height="8" viewBox="0 0 14 8" fill="" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.664 0V4L12.128 2.464L7.928 6.664L5.264 4L1.264 8L0.335999 7.064L5.272 2.128L7.936 4.8L11.2 1.536L9.664 0H13.664Z" fill="#e9672c"/>
+</svg>

+ 3 - 0
src/assets/images/carbon/svg/icon-top-left.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="19" viewBox="0 0 18 19" fill="none">
+<path d="M18 1H11C5.47715 1 1 5.47715 1 11V18.5" stroke="#75C4FF" stroke-width="2"/>
+</svg>

+ 3 - 0
src/assets/images/carbon/svg/icon-top-right.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="19" viewBox="0 0 18 19" fill="none">
+  <path d="M0 1L7 1C12.5228 1 17 5.47715 17 11L17 18.5" stroke="#75C4FF" stroke-width="2"/>
+</svg>

+ 3 - 0
src/assets/images/carbon/svg/icon-up.svg

@@ -0,0 +1,3 @@
+<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M13.664 0V4L12.128 2.464L7.928 6.664L5.264 4L1.264 8L0.335999 7.064L5.272 2.128L7.936 4.8L11.2 1.536L9.664 0H13.664Z" fill="#00FF00"/>
+</svg>

BIN
src/assets/images/carbon/底部.png


BIN
src/assets/images/carbon/替碳.png


BIN
src/assets/images/carbon/标题.png


BIN
src/assets/images/carbon/污水处理.png


BIN
src/assets/images/carbon/污泥处理.png


+ 8 - 0
src/assets/styles/common.scss

@@ -16,6 +16,14 @@
   font-style: normal;
 }
 
+@font-face {
+  // font-display: swap;
+  font-family: 'YouSheBiaoTiHei';
+  src: url('@/assets/fonts/YouSheBiaoTiHei.ttf');
+  // font-weight: normal;
+  // font-style: normal;
+}
+
 // chat 布局相关
 .chat-ask_icon,
 .chat-answer_icon {

+ 24 - 0
src/assets/svgs/carbon/icon-back.svg

@@ -0,0 +1,24 @@
+<svg width="52" height="52" viewBox="0 0 52 52" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_dd_2983_427)">
+<path d="M38.266 25.3609L34.0994 20.14C33.8986 19.889 33.5974 19.7551 33.2794 19.7551C33.1623 19.7551 33.0451 19.7718 32.928 19.822C32.5097 19.9726 32.2252 20.3575 32.2252 20.8093V23.9385H23.9087C22.7541 23.9385 21.8337 24.8756 21.8337 26.0135C21.8337 27.1681 22.7708 28.0884 23.9087 28.0884H32.2419V31.2176C32.2419 31.6527 32.5264 32.0543 32.9447 32.2049C33.0619 32.2384 33.179 32.2718 33.2962 32.2718C33.6141 32.2718 33.9153 32.138 34.1161 31.887L38.2827 26.6828C38.5672 26.2812 38.5672 25.729 38.266 25.3609ZM28.0753 34.3301H19.7253C18.5875 34.3301 17.6504 33.393 17.6504 32.2551V19.7384C17.6504 18.6005 18.5875 17.6801 19.7421 17.6801H28.0753C29.2299 17.6801 30.167 16.7431 30.167 15.6052C30.167 14.4673 29.2299 13.5302 28.0753 13.5302H17.6671C15.3746 13.5302 13.5005 15.4044 13.5005 17.6969V34.3635C13.5005 36.6728 15.3746 38.5302 17.6671 38.5302H28.0753C29.2299 38.5302 30.167 37.5931 30.167 36.4552C30.167 35.2672 29.2299 34.3301 28.0753 34.3301Z" fill="#B8DDFA"/>
+<path d="M37.8752 25.6728L37.8752 25.6728L37.879 25.6775C38.0221 25.8524 38.0413 26.1491 37.8819 26.3834L33.7258 31.5745L33.7257 31.5746C33.6264 31.6987 33.4732 31.7718 33.2962 31.7718C33.2631 31.7718 33.2177 31.7625 33.1006 31.7294C32.8841 31.6451 32.7419 31.4331 32.7419 31.2176V28.0884V27.5884H32.2419H23.9087C23.0443 27.5884 22.3337 26.8893 22.3337 26.0135C22.3337 25.1491 23.0329 24.4385 23.9087 24.4385H32.2252H32.7252V23.9385V20.8093C32.7252 20.5773 32.8689 20.3748 33.0974 20.2925L33.1113 20.2875L33.125 20.2816C33.1648 20.2646 33.2114 20.2551 33.2794 20.2551C33.4564 20.2551 33.6096 20.3283 33.7089 20.4523C33.7089 20.4523 33.7089 20.4523 33.7089 20.4523L37.8752 25.6728ZM19.7253 34.8301H28.0753C28.9486 34.8301 29.667 35.5381 29.667 36.4552C29.667 37.3144 28.9564 38.0302 28.0753 38.0302H17.6671C15.6495 38.0302 14.0005 36.3953 14.0005 34.3635V17.6969C14.0005 15.6805 15.6508 14.0302 17.6671 14.0302H28.0753C28.9564 14.0302 29.667 14.746 29.667 15.6052C29.667 16.4643 28.9564 17.1801 28.0753 17.1801H19.7421C18.3192 17.1801 17.1504 18.3165 17.1504 19.7384V32.2551C17.1504 33.6691 18.3113 34.8301 19.7253 34.8301Z" stroke="#DAF3FF"/>
+</g>
+<defs>
+<filter id="filter0_dd_2983_427" x="0.500487" y="0.530211" width="50.9935" height="51" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="6.5"/>
+<feComposite in2="hardAlpha" operator="out"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.0962461 0 0 0 0 0.354998 0 0 0 0 0.7 0 0 0 1 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2983_427"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="3.5"/>
+<feComposite in2="hardAlpha" operator="out"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.182515 0 0 0 0 0.425868 0 0 0 1 0"/>
+<feBlend mode="normal" in2="effect1_dropShadow_2983_427" result="effect2_dropShadow_2983_427"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_2983_427" result="shape"/>
+</filter>
+</defs>
+</svg>

+ 12 - 0
src/assets/svgs/tool/add-symbol.svg

@@ -0,0 +1,12 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_2784_3195)">
+<path d="M8.00004 14.6654C11.6819 14.6654 14.6667 11.6806 14.6667 7.9987C14.6667 4.3168 11.6819 1.33203 8.00004 1.33203C4.31814 1.33203 1.33337 4.3168 1.33337 7.9987C1.33337 11.6806 4.31814 14.6654 8.00004 14.6654Z" stroke="#2454FF" stroke-linejoin="round"/>
+<path d="M8 5.33203V10.6654" stroke="#2454FF" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M5.33337 8H10.6667" stroke="#2454FF" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0_2784_3195">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 3 - 0
src/assets/svgs/tool/setp-arrow-right.svg

@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.3125 3.625L8.6875 7L5.3125 10.375" stroke="#B0B7C0" stroke-width="1.125" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 64 - 0
src/components/BaseNumberInput/index.vue

@@ -0,0 +1,64 @@
+<script setup>
+import { NInputNumber } from 'naive-ui';
+defineProps({
+  unit: {
+    type: String,
+    default: ''
+  },
+  placeholder: {
+    type: String,
+    default: '请输入'
+  }
+});
+
+const modelValue = defineModel('value');
+
+const inputThemeOverrides = {
+  peers: {
+    Input: {
+      text: '#333',
+      border: '1px solid #d7d9e5',
+      borderRadius: '8px',
+      borderHover: '1px solid #2454FF',
+      borderFocus: '1px solid #2454FF',
+      boxShadowFocus: '0 0 0 2px rgba(36, 84, 255, 0.2)'
+    }
+  }
+}
+</script>
+
+<template>
+  <NInputNumber :placeholder="placeholder" :show-button="false" v-model:value="modelValue"
+    :theme-overrides="inputThemeOverrides" class="custom-input-number">
+    <template #suffix>
+      <div class="unit" v-if="unit">{{ unit }}</div>
+    </template>
+  </NInputNumber>
+</template>
+
+<style lang="scss" scoped>
+.unit {
+  flex-shrink: 1;
+  height: 100%;
+  padding: 0 8px;
+  border-radius: 0px 8px 8px 0px;
+  border-left: 0;
+  background: #F0F2F5;
+  text-align: center;
+  line-height: auto;
+  font-size: 12px;
+  font-weight: bold;
+}
+</style>
+
+<style lang="scss">
+.custom-input-number {
+  .n-input-wrapper {
+    padding-right: 0px;
+    // border: 1px solid #E6EAEE;
+    // .n-input__input-el, .n-input__placeholder {
+    //   font-size: 12px;
+    // }
+  }
+}
+</style>

+ 10 - 11
src/components/Chat/ChatAgentInput.vue

@@ -199,8 +199,9 @@ const selectOption = (index) => {
 }
 
 const beforeUpload = ({ file }) => {
-  if (( file.file?.size / ( 1024 * 2 ) ) > 5) {
-    message.warning("只能上传.doc、.docx、.txt格式的文件, 请重新上传");
+
+  if (( file.file?.size / ( 1024 * 1024 ) ) > 5) {
+    message.warning("文件大小超过5MB,请重新选择");
     return false;
   }
 
@@ -222,24 +223,21 @@ const handleUploadChange = ({ file }) => {
   if (file.status === 'uploading') {
     uploadFileList.value[lastFileListIndex.value].percentage = file.percentage;
   }
-
 }
 
 // 文件上传完成
 const handleFinish = ({ file, event }) => {
 
-  uploadLoading.value = false
-
   try {
 
     const res = JSON.parse( (event?.target).response );
 
     if ( res.code == 200 ) {
-      
       uploadFileList.value[lastFileListIndex.value] = {
         ...uploadFileList.value[lastFileListIndex.value],
         url: res.data,
       }
+      uploadLoading.value = false
     }
 
   } catch (error) {
@@ -255,7 +253,8 @@ const handleUploadError = (error) => {
 
 // 删除文件
 const onRemoveFile = (i) => {
-  uploadFileList.value.splice(i, 1);
+  // uploadFileList.value.splice(i, 1);
+  uploadFileList.value = [];
 }
 
 const clearFileList = () => {
@@ -321,8 +320,8 @@ defineExpose({
                   <span class="size">{{ item.size }}</span>
                 </p>
               </div>
-              <span class="close" @click="onRemoveFile(i)" v-show="item.percentage == 100">x</span>
-              <div class="file-progress" v-if="item.percentage != 100">
+              <span class="close" @click="onRemoveFile(i)" v-show="item.percentage == 100 && !uploadLoading">x</span>
+              <div class="file-progress" v-if="uploadLoading">
                 <NProgress
                   type="line"
                   color="#3153f5"
@@ -338,7 +337,7 @@ defineExpose({
             <div class="inp-wrapper flex-1" @click="handleInpFocus">
               <div class="upload-inner">
                 <NUpload
-                  accept=".doc, .docx, .txt"
+                  accept=".doc, .docx, .pdf, .txt"
                   :disabled="uploadLoading"
                   :show-file-list="false"
                   :action="baseURL + '/qiniuyun/upLoadImage'"
@@ -354,7 +353,7 @@ defineExpose({
                     <template #trigger>
                       <div class="upload-file-button"></div>
                     </template>
-                    <span class="text-[12px]">支持上传文件(每次一个, 大小5MB以内)接受.doc、.docx、.txt等格式的文件</span>
+                    <span class="text-[12px]">支持上传文件(每次一个, 大小5MB以内)接受.doc、.docx、.pdf、.txt等格式的文件</span>
                   </NTooltip>
                 </NUpload>
               </div>

+ 5 - 0
src/components/Layout/TheMenu.vue

@@ -95,6 +95,11 @@ const menuOptions = [
     icon: renderIcon({ name: 'menu-work' }),
     key: '/work'
   },
+  {
+    label: () => renderLabel('碳排放'),
+    icon: renderIcon({ name: 'menu-work' }),
+    key: '/carbon'
+  },
   {
     label: () => renderLabel('用户中心'),
     icon: renderIcon({ name: 'menu-user' }),

+ 5 - 1
src/components/index.js

@@ -25,6 +25,8 @@ import editPassword from "./Dialog/editPassword.vue";
 
 import userTop from "./Layout/userTop.vue";
 
+import BaseNumberInput from "./BaseNumberInput/index.vue"
+
 
 export {
 
@@ -50,5 +52,7 @@ export {
   contactUs,
   userEdit,
   editPassword,
-  userTop
+  userTop,
+
+  BaseNumberInput
 }

+ 1 - 1
src/composables/useInfinite.js

@@ -1,4 +1,4 @@
-import { ref, unref, onMounted, computed, watch } from "vue";
+import { ref, unref, onMounted, computed } from "vue";
 import { chatApi } from '@/api/chat';
 
 export const useInfinite = (path, props) => {

+ 73 - 0
src/composables/useTable.js

@@ -0,0 +1,73 @@
+import { ref, onMounted } from 'vue';
+
+export const useTable = () => {
+
+  const config = {
+    test : {
+      a: {
+        columns: ['碳源名称', '外加碳源用量', '操作']
+      },
+      b: {
+        columns: ['碳源名称', '外加碳源用量', '操作']
+      }
+    }
+
+  }
+
+  const tableData = ref({
+    sewageCo2First: [],
+    energyFirst: [],
+    energySecond: [],
+    mudFirst: [
+      {
+        columns: ['燃烧类型', '污泥处理焚烧量', '污泥焚烧过程N₂O的排放因子'],
+        data: [
+            { type: 'select', value: '', key: 'wnclBwqrsRslx' },
+            { type: 'input', value: null, unit: 't干污泥/月', key: 'wnclBwqrsFsl' },
+            { type: 'input', value: null, unit: 'tkg N₂O/t 干污泥', key: 'wnclBwqrsPfyz' }
+        ]
+      }
+    ],
+    mudSecond: [
+      {
+        columns: ['反应堆类型', '污泥热解消耗量', '污泥热解过程N₂O的排放因子'],
+        data: [
+            { type: 'select', value: '', key: 'wnclWnrjQtLx' },
+            { type: 'input', value: null, unit: 't干污泥/月',  key: 'wnclWnrjQtXhl' },
+            { type: 'input', value: null, unit: 'tkg N₂O/t 干污泥', key: 'wnclWnrjQtPfyz' }
+        ]
+      }
+    ],
+    carbonFirst: [],
+    carbonSecond: [
+      {
+        columns: ['水厂规模', '回用水供应量'],
+        data: [
+            { type: 'select', value: '', key: 'thZssScgm' },
+            { type: 'input', value: null, unit: 'm³/月', key: '', key: 'thZssGyl' },
+        ]
+      }
+    ],
+    carbonThird: [],
+    carbonFourth: []
+  });
+
+  const addTable = (key, option) => {
+    tableData.value[key].push(option);
+  }
+
+  const removeTable = ({ name: key, index }) => {
+    tableData.value[key].splice(index, 1);
+  }
+
+  onMounted(async () => {
+    // const { data } = await chatApi.getWelcomeRecommend(type);
+    // recommendList.value = data;
+  })
+
+  return {
+    addTable,
+    tableData,
+    removeTable
+  }
+}

+ 2 - 1
src/main.ts

@@ -8,7 +8,8 @@ import './permission'
 import 'virtual:svg-icons-register'
 import './assets/styles/tailwind.css'
 import './assets/styles/index.scss'
-import './utils/resize';
+// import './utils/resize';
+import '@vuepic/vue-datepicker/dist/main.css'
 
 const app = createApp(App)
 

+ 16 - 8
src/router/index.js

@@ -9,6 +9,14 @@ const constantRouterMap = [
       title: "智慧总控"
     }
   },
+  {
+    path: '/carbon',
+    name: 'carbon',
+    component: () => import('@/views/carbon/index.vue'),
+    meta: {
+      title: "碳排放"
+    }
+  },
   // {
   //   path: '/test',
   //   name: 'TempTest',
@@ -23,14 +31,14 @@ const constantRouterMap = [
    * 注释时间: 2024年08月05日15:03:02
    * 
    * */ 
-  {
-    path: '/count1',
-    name: 'count1',
-    component: () => import('@/views/count/index1.vue'),
-    meta: {
-      title: "临时统计1"
-    }
-  },
+  // {
+  //   path: '/count1',
+  //   name: 'count1',
+  //   component: () => import('@/views/count/index1.vue'),
+  //   meta: {
+  //     title: "临时统计1"
+  //   }
+  // },
   // {
   //   path: '/count2',
   //   name: 'count2',

+ 61 - 0
src/views/carbon/components/BaseCard.vue

@@ -0,0 +1,61 @@
+<script setup>
+import { ref } from 'vue';
+defineProps({
+  title: {
+    type: String,
+    default: ''
+  },
+  subTitle: {
+    type: String,
+    default: ''
+  },
+  bgColorType: {
+    type: String,
+    default: 'default'
+  }
+})
+</script>
+
+<template>
+  <div :class="['card-wrapper', 'card-bg_' + bgColorType]">
+    <div class="header" v-if="title">
+      <h4 class="title">{{ title }}</h4>
+      <span class="subtitle">{{ subTitle }}</span>
+    </div>
+    <div class="content space-y-[14px]">
+      <slot />
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.card-wrapper {
+  padding: 20px 14px 20px 14px;
+  border-radius: 10px;
+  border: 0.5px solid #FFF;
+
+  .header {
+    @include flex(x, center, start);
+    margin-bottom: 24px;
+    line-height: 24px;
+    .title {
+      margin-right: 10px;
+      font-size: 15px;
+      font-weight: bold;
+      color: #1A2029;
+    }
+    .subtitle {
+      font-size: 14px;
+      color: #B0B7C0;
+    }
+  }
+}
+
+.card-bg_default {
+  background: #fff;
+}
+
+.card-bg_gradient {
+  background: linear-gradient(91deg, #EBF4FF 0.78%, #EBFAFF 23.21%, #F8F7FF 42.76%, #F1FDF9 62.59%, #FFFAF3 98.35%);
+}
+</style>

+ 104 - 0
src/views/carbon/components/BaseDatePicker.vue

@@ -0,0 +1,104 @@
+<script setup>
+import { ref, computed } from 'vue';
+import { c, NPopover } from 'naive-ui';
+import VueDatePicker from '@vuepic/vue-datepicker';
+import dayjs from 'dayjs';
+
+const dateValue = ref(null);
+const popoverTriggerRef = ref(null);
+const modelValue = defineModel('value');
+const modelFormatValue = defineModel('formatValue');
+import { addMonths, getMonth, getYear, subMonths } from 'date-fns';
+const props = defineProps({
+  isNoInp: {
+    type: Boolean,
+    default: false
+  },
+  dark: {
+    type: Boolean,
+    default: false
+  },
+  disabledMonth: {
+    type: Array,
+    default:() => []
+  }
+})
+
+const onSelectMonth = (time) => {
+  const month = time.month < 9 ? `0${time.month + 1}` : time.month + 1;
+  const timeStr = `${time.year}-${month}`;
+  const date = dayjs(timeStr, 'YYYY-MM');
+  const timestamp = date.valueOf();
+  dateValue.value = time;
+  modelValue.value = timestamp;
+  modelFormatValue.value = timeStr;
+  setTimeout(() => popoverTriggerRef.value.setShow(false), 200);
+}
+
+// const allowedDates = (val) => {
+//   console.log(val);
+//   return [ new Date()]
+// }
+
+const allowedDates = computed(() => {
+  console.log(new Date());
+  const a = dayjs('2024-4', 'YYYY-M').format()
+  console.log(a);
+  return [
+  a
+  ];
+});
+// const allowedDates = (date) => {
+//   // 获取当前日期的月份
+//   const month = date.getMonth(); // 月份是从 0 开始的,0 代表一月
+//   // 禁用特定月份,例如 3 月和 4 月
+//   return ![3, 4].includes(month);
+// };
+
+const filters = computed(() => {
+  const currentDate = new Date()
+  return {
+    months: Array.from(Array(3).keys())
+            .map((item) => {
+              console.log( getMonth(addMonths(currentDate, item + 1)) );
+              return getMonth(addMonths(currentDate, item + 1))
+            })
+  }
+})
+
+
+const disabledDates = computed(() => {
+  const today = new Date();
+
+  const tomorrow = new Date(today)
+  tomorrow.setDate(tomorrow.getDate() + 1)
+
+  const afterTomorrow = new Date(tomorrow);
+  afterTomorrow.setDate(tomorrow.getDate() + 1);
+  console.log( tomorrow );
+
+  const date = dayjs('2024-06', 'YYYY-MM');
+
+  return [tomorrow, date]
+})
+</script>
+
+<template>
+  <NPopover trigger="click" raw :animated="false" ref="popoverTriggerRef">
+    <template #trigger>
+      <slot></slot>
+    </template>
+    <div>
+      <VueDatePicker month-picker inline locale="zh" v-model="dateValue" 
+        ref="datePickerRef" :dark="dark" :allowed-dates="allowedDates">
+        <template #action-row></template>
+      </VueDatePicker>
+    </div>
+  </NPopover>
+</template>
+
+<style lang="scss" scoped>
+:deep(.dp__overlay_cell_active) {
+  background-color: #2454FF;
+}
+</style>

+ 96 - 0
src/views/carbon/components/BasePanel.vue

@@ -0,0 +1,96 @@
+<script setup>
+import { ref } from 'vue';
+import { NScrollbar } from 'naive-ui';
+
+defineProps({
+  isXScroll: {
+    type: Boolean,
+    default: false
+  },
+  title: {
+    type: String,
+    default: ''
+  },
+  isNoPadding: {
+    type: Boolean,
+    default: false
+  }
+})
+</script>
+
+<template>
+  <div :class="['panel-item']" :style="{ paddingBottom: isNoPadding ? 0 : isXScroll ? '0' : '14px' }">
+    <div class="sub-title_inner">
+      <h4 class="title">{{ title }}</h4>
+      <slot name="side" />
+    </div>
+
+    <div class="content">
+      <template v-if="isXScroll">
+        <NScrollbar style="width: 100%;" x-scrollable>
+          <div class="inner space-x-[24px]">
+            <slot></slot>
+          </div>
+        </NScrollbar>
+      </template>
+
+      <template v-else>
+        <slot></slot>
+      </template>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.panel-item {
+  .sub-title_inner {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-bottom: 16px;
+
+    .add-btn {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 68px;
+      height: 30px;
+      border: 1px solid #2454FF;
+      border-radius: 4px;
+      font-size: 13px;
+      color: #2454FF;
+    }
+
+    .title {
+      // width: 368px;
+      height: 30px;
+      padding-left: 10px;
+      border-radius: 4px;
+      background: linear-gradient(90deg, #F6F7F9 0%, #FFFFFF 100%);
+      line-height: 30px;
+      font-size: 14px;
+      font-weight: bold;
+      color: #1A2029;
+    }
+  }
+
+  .content {
+    .inner {
+      display: flex;
+      flex-wrap: nowrap;
+      padding-bottom: 16px;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.panel-item {
+  .content {
+    .n-form-item {
+      width: 214px;
+      flex-shrink: 0;
+    }
+  }
+}
+</style>

+ 83 - 0
src/views/carbon/components/BaseStep.vue

@@ -0,0 +1,83 @@
+<script setup>
+import BaseCard from './BaseCard.vue';
+
+const stepsData = [
+  { title: '基础信息', subTtile: '碳排放管理基础信息填写', color: '#2454FF' },
+  { title: '污水处理', subTtile: '生化反应碳排', color: '#24CCFF' },
+  { title: '水厂', subTtile: '能源、药剂碳排', color: '#7969F9' },
+  { title: '污泥处理', subTtile: '生化反应总碳排', color: '#3FC56E' },
+  { title: '替碳、碳汇', subTtile: '替碳、碳汇基础信息填写', color: '#F59B14' },
+]
+
+</script>
+<template>
+  <div class="steps-list">
+    <div class="steps-item" v-for="item, index in stepsData" :key="index">
+      <p class="steps-title space-x-[6px]">
+        <span class="num" :style="{ color: item.color }">{{ '0' + (index + 1) }}</span>
+        <span class="title">{{ item.title }}</span>
+      </p>
+      <p class="steps-subtitle">{{ item.subTtile }}</p>
+      <p class="line" :style="{ background: item.color }"></p>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.steps-list {
+  @include flex(x, center, between);
+
+  .steps-item {
+    position: relative;
+    width: 214px;
+    height: 84px;
+    padding: 14px 26px;
+    border: 1px dashed #E6EAEE;
+    border-radius: 8px;
+    background: #fff;
+
+    .steps-title {
+      padding-bottom: 6px;
+      margin-bottom: 6px;
+      border-bottom: 1px solid #EEEEEE;
+      font-size: 18px;
+      line-height: 24px;
+      font-weight: bold;
+    }
+
+    .steps-subtitle {
+      font-size: 12px;
+      line-height: 14px;
+      color: #9E9E9E;
+    }
+
+    .line {
+      position: absolute;
+      top: 0px;
+      left: 24px;
+      width: 18px;
+      height: 2px;
+      gap: 0px;
+      border-radius: 0px 0px 1px 1px;
+    }
+
+    &:not(:last-child) {
+      &::after {
+        content: ' ';
+        position: absolute;
+        top: 50%;
+        right: -15px;
+        transform: translateY(-50%);
+        width: 24px;
+        height: 24px;
+        border-radius: 100%;
+        border: 1px solid #fff;
+        position: absolute;
+        box-shadow: 0px 3px 6px 0px #C6C6C640;
+        background: #F4F4F4 url("@/assets/svgs/tool/setp-arrow-right.svg") center center no-repeat;
+        z-index: 10;
+      }
+    }
+  }
+}
+</style>

+ 162 - 0
src/views/carbon/components/BaseTable.vue

@@ -0,0 +1,162 @@
+<script setup>
+import { ref } from 'vue';
+import { NSelect, NInputNumber } from 'naive-ui';
+
+const props = defineProps({
+  data: {
+    type: Array,
+    default: () => []
+  },
+  name: {
+    type: String,
+    default: () => ''
+  },
+  avgColumn: {
+    type: Boolean,
+    default: false
+  },
+  options: {
+    type: Array,
+    default: () => []
+  }
+})
+
+const emit = defineEmits(['on-remove']);
+
+const selectThemeOverrides = {
+  peers: {
+    InternalSelection: {
+      border: '0px solid #ccc',
+      borderRadius: '8px',
+      textColor: '#333'
+    }
+  }
+}
+
+const inputThemeOverrides = {
+  peers: {
+    Input: {
+      border: '0px solid #d7d9e5',
+      borderRadius: '8px',
+      borderHover: '1px solid #2454FF',
+      borderFocus: '1px solid #2454FF',
+      boxShadowFocus: '0 0 0 2px rgba(36, 84, 255, 0.2)',
+      text: '#333'
+    }
+  }
+}
+
+const onRemove = (index) => {
+  emit('on-remove', {
+    name: props.name,
+    index
+  });
+}
+
+</script>
+
+<template>
+  <div class="table-wrapper">
+
+    <div class="flex items-center justify-center py-[10px] bg-[#fff] text-[#B0B7C0]" v-if="data.length == 0">
+      <span>未添加</span>
+    </div>
+
+    <template v-if="data.length > 0">
+      <div :class="['table-box', { 'table-avg-column': avgColumn }]" v-for="item, index in data" :key="index">
+        <ul class="header">
+          <li :class="['th', { 'text-center': item.columns.length - 1 === index }]" :key="index" v-for="val, index in item.columns">{{ val }}</li>
+        </ul>
+        <div class="body">
+          <ul class="t-row_tr">
+            <li class="td" v-for="val, i in item.data" :key="i">
+              <template v-if="val.type === 'name'">
+                <span class="text-left pl-[12px] name">{{ val.value }}</span>
+              </template>
+  
+              <template v-if="val.type === 'select'">
+                <NSelect v-model:value="val.value" :options="options" :theme-overrides="selectThemeOverrides" />
+              </template>
+  
+              <template v-if="val.type === 'input'">
+                <NInputNumber v-model:value="val.value" :show-button="false" class="w-full"
+                  :theme-overrides="inputThemeOverrides">
+                  <template #suffix>
+                    <span>{{ val.unit }}</span>
+                  </template>
+                </NInputNumber>
+              </template>
+  
+              <template v-if="val.type === 'text'">
+                <li class="td text-center cursor-pointer text-[#2454FF]" @click="onRemove(index)">删除</li>
+              </template>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </template>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.table-wrapper {
+  padding: 10px;
+  border-radius: 8px;
+  background: #F6F7F9;
+
+  .table-box {
+    background: #fff;
+    filter: drop-shadow(0px 4px 4px rgba(197, 196, 196, 0.25));
+
+    &:not(:last-child) {
+      margin-bottom: 10px;
+    }
+
+    .header,
+    .t-row_tr {
+      width: 100%;
+      display: flex;
+      height: 42px;
+
+      .th,
+      .td {
+        width: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: flex-start;
+        padding: 0px 24px;
+        font-size: 14px;
+        overflow: hidden;
+        
+        &:not(:last-child) {
+          border-right: 1px solid #E6EAEE;
+        }
+
+        &:last-child {
+          justify-content: center;
+          width: 150px;
+          flex-shrink: 0;
+        }
+
+        .name {
+          display: inline-block;
+          overflow:hidden;
+          text-overflow:ellipsis;
+          white-space:nowrap;
+        }
+      }
+    }
+
+    .t-row_tr {
+      border-top: 1px solid #E6EAEE;
+    }
+  }
+
+  .table-avg-column {
+    .header .th:last-child, .t-row_tr .td {
+      flex-shrink: 1 !important;
+      width: 50% !important;
+    }
+  }
+}
+</style>

+ 775 - 0
src/views/carbon/components/TheDrawerForm.vue

@@ -0,0 +1,775 @@
+<script setup>
+import { ref, unref, onMounted } from 'vue';
+import { NDrawer, NDrawerContent, NForm, NSelect, NFormItem, NDatePicker, useMessage, NScrollbar } from 'naive-ui';
+import { SvgIcon, BaseNumberInput } from '@/components';
+import { BaseCard, BaseStep, BaseTable, BasePanel, BaseDatePicker } from './index';
+import { useTable } from '@/composables/useTable';
+import { inputConfig } from './config';
+import { inputHasBorderThemeOverrides } from '../tools/resetTheme';
+import VueDatePicker from '@vuepic/vue-datepicker';
+
+
+import { carbonApi } from '@/api/carbon'
+import dayjs from 'dayjs';
+
+const BASE_RULES = { required: true, trigger: ['blur'], type: 'number' };
+
+const message = useMessage();
+const { addTable, removeTable, tableData } = useTable();
+
+const inpConfig = ref(inputConfig);
+
+const spliceInpData = ref([]);
+
+const datePickerRef = ref(null);
+const disabledMonth = ref(null);
+
+const isVisibleDrawer = defineModel();
+const formValue = ref({});
+const selectCodeSet = ref({});
+const selectValue = ref({});
+const checkedTymcValue = ref([]);
+
+const formRef = ref(null);
+const switchCo2State = ref(0);
+const tabCo2Data = ['泵站和沉砂池逸散的CH₄量(实测)', '泵站和沉砂池逸散的CH₄量(未实测)']
+
+const rules = {
+  provinceId: [
+    { required: true, trigger: 'blur', type: 'number' }
+  ],
+  addYearMonth: [
+    { required: true, trigger: 'blur', type: 'number' }
+  ]
+}
+
+const switchTabs = (index) => {
+  switchCo2State.value = index;
+  if (index == 1) {
+    spliceInpData.value = inpConfig.value.sewage.twoBlock.splice(4);
+  } else {
+    inpConfig.value.sewage.twoBlock = [...inpConfig.value.sewage.twoBlock, ...spliceInpData.value]
+  }
+}
+
+const getCodeSetInfo = ({ key, code }) => {
+  return selectCodeSet.value[key].find(({ dictCode }) => dictCode == code);
+}
+
+// 表格添加
+const handleAddTableRow = (key) => {
+
+  let option = {};
+
+  if (key === 'sewageCo2First') {
+
+    const ids = [135]; // 复合碳源
+
+    if (!selectValue.value.tymc) {
+      return message.warning("请先选择碳源名称");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'tymcOptions',
+      code: selectValue.value.tymc
+    });
+
+    const isExists = ids.includes(codeSet.dictCode);
+
+    option = {
+      columns: ['碳源名称', isExists ? '有效COD质量' : '外加碳源用量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: '', unit: 'Kg/月' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 0
+    }
+
+  }
+
+  if (key === 'energyFirst') {
+
+    const ids = [181, 182];
+
+    if (!selectValue.value.hsrl) {
+      return message.warning("请先选择固液气-化石燃料");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'hsrlOptions',
+      code: selectValue.value.hsrl
+    });
+
+    const isExists = ids.includes(codeSet.dictCode);
+
+    option = {
+      columns: ['燃料名称', '燃料消耗量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: null, unit: isExists ? 'm³/月' : 't/月' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 1
+    }
+
+  }
+
+  if (key === 'energySecond') {
+
+    const ids = [143];
+
+    if (!selectValue.value.yjmc) {
+      return message.warning("请先选择药剂名称");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'yjmcOptions',
+      code: selectValue.value.yjmc
+    });
+
+    const isExists = ids.includes(codeSet.dictCode);
+
+    option = {
+      columns: ['药剂名称', isExists ? '有效COD质量' : '药剂消耗量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: null, unit: 'Kg/月' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 2
+    }
+
+  }
+
+
+  if (key === 'carbonFirst') {
+
+    if (!selectValue.value.gyittOne) {
+      return message.warning("请先选择固液气-替碳");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'gyittOptions',
+      code: selectValue.value.gyittOne
+    });
+
+    option = {
+      columns: ['燃料名称', '热泵供热、供冷量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: null, unit: 'Kg/月' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 3
+    }
+
+  }
+
+
+  if (key === 'carbonThird') {
+
+    if (!selectValue.value.gyittTwo) {
+      return message.warning("请先选择固液气-替碳");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'gyittOptions',
+      code: selectValue.value.gyittTwo
+    });
+
+    option = {
+      columns: ['燃料名称', '污泥厌氧消化沼气发电量', '厌氧消化沼气富余热能利用量', '沼气提纯并网的天然气量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: null, unit: 'kW·h/月' },
+        { type: 'input', value: null, unit: 'TJ/月' },
+        { type: 'input', value: null, unit: 'm³ CH₄/月' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 4
+    }
+
+  }
+
+
+  if (key === 'carbonFourth') {
+
+    if (!selectValue.value.gyittThree) {
+      return message.warning("请先选择固液气-替碳");
+    }
+
+    const codeSet = getCodeSetInfo({
+      key: 'gyittOptions',
+      code: selectValue.value.gyittThree
+    });
+
+    option = {
+      columns: ['燃料名称', '污泥焚烧或热解的电力利用量', '污泥焚烧或热解热能利用量', '沼气提纯并网的天然气量', '操作'],
+      data: [
+        { type: 'name', value: codeSet.dictLabel },
+        { type: 'input', value: null, unit: 'kW·h/月' },
+        { type: 'input', value: null, unit: 't/d' },
+        { type: 'input', value: null, unit: 'mKJ/Kg' },
+        { type: 'text' }
+      ],
+      codeSet,
+      type: 5
+    }
+  }
+
+  addTable(key, option);
+}
+
+// 格式化时间
+const formatData = () => {
+  const { provinceId, addYearMonth, wsSjclCh4Tsb, wsSjclCh4Csc } = unref(formValue);
+  const provinceName = selectCodeSet.value.areaOptions.find(item => item.dictCode === provinceId)?.dictLabel;
+  const tempObj = {};
+
+  const extraList = Object.keys(tableData.value).map(key => {
+    const whiteList = ['sewageCo2First', 'energyFirst', 'energySecond', 'carbonFirst', 'carbonThird', 'carbonFourth' ];
+    const tempArr = [];
+    const commonItem = unref(tableData)[key];
+    if ( whiteList.includes(key) ) {
+      const result = commonItem.map(({ codeSet, data, type }) => {
+        const [_, amount, lyl, hz] = data || []; 
+        return {
+          dictCode: codeSet.dictCode,
+          dictLabel: codeSet.dictLabel,
+          type,
+          amount: amount?.value,
+          lyl: lyl?.value,
+          hz: hz?.value
+        }
+      });
+      tempArr.push(result)
+    } else {
+      const [ item ] = commonItem;
+      item.data.forEach(child => tempObj[child.key] = child.value);
+    }
+    return tempArr;
+  }).filter(item => item.length).flat(Infinity);
+
+  return {
+    ...formValue.value,
+    ...tempObj,
+    wsSjclCh4Tsb: wsSjclCh4Tsb === 0 ? wsSjclCh4Tsb : null,
+    wsSjclCh4Csc: wsSjclCh4Csc === 0 ? wsSjclCh4Csc : null,
+    addYearMonth: dayjs(addYearMonth).format('YYYY-MM'),
+    provinceName,
+    extraList
+  };
+}
+
+const onSubmit = ( e ) => {
+  e.preventDefault();
+  formRef.value?.validate( async (errors) => {
+    const params = formatData();
+
+    const data = await carbonApi.postCarbonSmart(params);
+    console.log( data );
+    message.success("提交成功");
+    if (!errors) {
+      console.log("验证成功");
+    } else {
+      message.error("提交失败, 请检查");
+    }
+  });
+}
+
+// 获取值集
+const getAllCodeSet = async () => {
+
+  const { data: areaOptions } = await carbonApi.getCodeSet('ss_hl');
+  const { data: tymcOptions } = await carbonApi.getCodeSet('wjtykh_tymc');
+  const { data: hsrlOptions } = await carbonApi.getCodeSet('gyq_hsrl');
+  const { data: yjmcOptions } = await carbonApi.getCodeSet('wscljd_yjxh_yjmc');
+  const { data: gyittOptions } = await carbonApi.getCodeSet('gyq_tt');
+
+  selectCodeSet.value = {
+    areaOptions: areaOptions,
+    tymcOptions,
+    hsrlOptions,
+    yjmcOptions,
+    gyittOptions,
+    fireOptions: [
+      { label: '半连续-加煤机', value: 0 },
+      { label: '半连续-流化床', value: 1 },
+      { label: '间歇性-加煤机', value: 2 },
+      { label: '间歇性-流化床', value: 3 },
+      { label: '连续燃烧', value: 4 }
+    ],
+    reactOptions: [
+      { label: '竖井类型', value: 0 },
+      { label: '流化床式', value: 1 },
+      { label: '回转窑式', value: 2 }
+    ],
+    scgmOptions: [
+      { label: '小型', value: 0 },
+      { label: '中型', value: 1 },
+      { label: '大型', value: 2 }
+    ]
+  }
+
+}
+
+onMounted(async () => {
+  getAllCodeSet();
+})
+
+const closeDatePicker = (test) => {
+  formValue.value.time = test
+  console.log(test);
+  console.log(dayjs(test).format('YYYY-MM'));
+  // console.log( datePickerRef.value, datePickerRef.value.closeMenu );
+  datePickerRef.value.closeMenu();
+}
+
+const dateDisabled = (ts) => {
+  return disabledMonth.value.includes(dayjs(ts).format('YYYY-MM'));
+}
+
+const onAfterdEnter = async () => {
+  return
+  const { data: month } = await carbonApi.getAllMonth();
+  disabledMonth.value = month;
+  // disabledMonth.value = month.map(m => dayjs(m, 'YYYY-MM'));
+}
+onMounted(async () => {
+  const { data: month } = await carbonApi.getAllMonth();
+  disabledMonth.value = month;
+})
+
+</script>
+
+<template>
+  <NDrawer class="drawer-wrapper" placement="right" :width="1220" :close-on-esc="false" v-model:show="isVisibleDrawer"
+    :on-after-enter="onAfterdEnter" :auto-focus="false">
+    <n-drawer-content closable title="新建核算" header-class="drawer-header" body-content-class="drawer-body"
+      footer-class="drawer-footer">
+
+      <div class="main-container space-y-[12px]">
+        <NScrollbar style="height: 100%;">
+
+          <BaseCard bgColorType="gradient" style="margin-bottom: 12px;">
+            <BaseStep></BaseStep>
+          </BaseCard>
+
+          <NForm class="space-y-[12px] from-wrapper" ref="formRef" :model="formValue" :show-feedback="false">
+            <BaseCard title="基础信息" sub-title="碳排放管理基础信息填写">
+              <div class="flex space-x-[24px]">
+
+                <NFormItem label="省/直辖市" path="provinceId" label-placement="left" class="w-[343px]" :rule="BASE_RULES">
+                  <NSelect v-model:value="formValue.provinceId" :options="selectCodeSet.areaOptions"
+                    value-field="dictCode" label-field="dictLabel" />
+                </NFormItem>
+
+                <NFormItem label="核算时间" path="addYearMonth" label-placement="left" class="w-[343px]" :rule="BASE_RULES">
+                  <NDatePicker type="month" placeholder="请选择" v-model:value="formValue.addYearMonth"
+                    class="w-full custom-date-picker" :is-date-disabled="dateDisabled"
+                    :theme-overrides="inputHasBorderThemeOverrides" actions="confirm"></NDatePicker>
+                </NFormItem>
+
+              </div>
+            </BaseCard>
+
+            <BaseCard title="污水处理" sub-title="生化碳排">
+              <BasePanel isXScroll title="化石源碳矿化产生的碳排放量">
+                <NFormItem label-placement="top" :label="item.label" :path="item.key"
+                  v-for="item, index in inpConfig.sewage.oneBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel title="外加碳源矿化产生的化石源CO₂碳排放量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.tymc" :options="selectCodeSet.tymcOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('sewageCo2First')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                
+                <BaseTable :data="tableData.sewageCo2First" name="sewageCo2First"
+                  @on-remove="(name, index) => removeTable(name, index)"></BaseTable>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污水收集提升和处理阶段排放的CH₄的CO₂当量">
+                <template #side>
+                  <ul class="tabs space-x-[12px]">
+                    <li v-for="item, index in tabCo2Data"
+                      :class="['tab-item', { 'tab-actvie': index === switchCo2State }]" :key="index"
+                      @click="switchTabs(index)">{{ item }}</li>
+                  </ul>
+                </template>
+                <NFormItem label-placement="top" :label="item.label" :path="item.key"
+                  v-for="item, index in inpConfig.sewage.twoBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污水生物处理脱氮过程排放的N₂O的CO₂当量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sewage.threeBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+            </BaseCard>
+
+            <BaseCard title="能源、药剂碳排" sub-title="生化反应碳排">
+              <BasePanel isXScroll title="污水厂电力消耗产生的碳排放量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.energy.oneBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel isXScroll title="净购入热力消耗产生的碳排放量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.energy.twoBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel title="固定式能源燃料消耗产生的碳排放量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.hsrl" :options="selectCodeSet.hsrlOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('energyFirst')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                <BaseTable :data="tableData.energyFirst" name="energyFirst"
+                  @on-remove="(name, index) => removeTable(name, index)">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel title="污水处理阶段药剂消耗产生的碳排放量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.yjmc" :options="selectCodeSet.yjmcOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('energySecond')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                <BaseTable :data="tableData.energySecond" name="energySecond"
+                  @on-remove="(name, index) => removeTable(name, index)"></BaseTable>
+              </BasePanel>
+
+            </BaseCard>
+
+            <BaseCard title="污泥处理" sub-title="生化反应碳排">
+              <BasePanel isXScroll title="污泥厌氧消化沼气收集管路无意泄露的CH₄或沼气火炬燃烧不充分导致的碳排放">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sludge.oneBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel isXScroll title="单独处理污泥厌氧消化过程产生的碳排放量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sludge.twoBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污泥好氧发酵过程生化反应的碳排放">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sludge.threeBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污泥干化焚烧或协同焚烧过程,化石源碳被氧化产生的化石源CO₂碳排放量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sludge.fourBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel title="污泥焚烧过程不完全燃烧产生的CH₄和N₂O的CO₂排放当量">
+                <BaseTable :data="tableData.mudFirst" name="mudFirst" avg-column :options="selectCodeSet.fireOptions">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污泥热解碳化或气化过程化石源CO₂碳排放量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.sludge.fiveBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel title="污泥热解碳化或气化过程产生的CH₄和N₂O的CO₂排放当量">
+                <BaseTable :data="tableData.mudSecond" name="mudSecond" avg-column
+                  :options="selectCodeSet.reactOptions">
+                </BaseTable>
+              </BasePanel>
+            </BaseCard>
+
+            <BaseCard title="替碳、碳汇" sub-title="是不是写一些什么">
+              <BasePanel title="热泵技术-替碳量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.gyittOne" :options="selectCodeSet.gyittOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('carbonFirst')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                <BaseTable :data="tableData.carbonFirst" name="carbonFirst"
+                  @on-remove="(name, index) => removeTable(name, index)">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel isXScroll title="光伏-替碳量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.carbon.oneBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+
+              <BasePanel title="再生水回用的替碳量(宜按替代的商业供水的取水、生产和输送的碳排放量计算)">
+                <BaseTable :data="tableData.carbonSecond" name="carbonSecond" avg-column
+                  :options="selectCodeSet.scgmOptions">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel title="污泥厌氧消化沼气利用的替碳量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.gyittTwo" :options="selectCodeSet.gyittOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('carbonThird')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                <BaseTable :data="tableData.carbonThird" name="carbonThird"
+                  @on-remove="(name, index) => removeTable(name, index)">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel title="污泥焚烧或热解热能利用的替碳量">
+                <template #side>
+                  <div class="flex items-center space-x-[14px]">
+                    <NSelect v-model:value="selectValue.gyittThree" :options="selectCodeSet.gyittOptions" class="w-[200px]"
+                      label-field="dictLabel" value-field="dictCode" />
+                    <button class="add-btn space-x-[4px]" @click="handleAddTableRow('carbonFourth')">
+                      <SvgIcon name="tool-add-symbol"></SvgIcon>
+                      <span>添加</span>
+                    </button>
+                  </div>
+                </template>
+                <BaseTable :data="tableData.carbonFourth" name="carbonFourth"
+                  @on-remove="(name, index) => removeTable(name, index)">
+                </BaseTable>
+              </BasePanel>
+
+              <BasePanel isXScroll title="污泥经过厌氧、好氧或碳化处理后,产生的替碳量">
+                <NFormItem label-placement="top" :path="item.key" :label="item.label"
+                  v-for="item, index in inpConfig.carbon.twoBlock" :key="index" :rule="BASE_RULES">
+                  <BaseNumberInput :unit="item.unit" v-model:value="formValue[item.key]"></BaseNumberInput>
+                </NFormItem>
+              </BasePanel>
+            </BaseCard>
+          </NForm>
+        </NScrollbar>
+      </div>
+      <template #footer>
+        <div class="w-full space-x-[8px] flex justify-center">
+          <button class="btn btn_primary" @click="onSubmit">提交并核算</button>
+          <button class="btn btn_default">暂存</button>
+        </div>
+      </template>
+    </n-drawer-content>
+  </NDrawer>
+  <div>
+
+    <!-- <NInput class="input" :theme-overrides="buttonThemeOverrides"></NInput> -->
+
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.drawer-picker {
+  position: relative;
+}
+
+.custom-input {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  z-index: 10;
+}
+
+.main-container {
+  height: 100%;
+  padding: 21px 24px;
+  border-radius: 20px;
+  border: 1px solid #FFF;
+  background: linear-gradient(180deg, rgba(238, 253, 255, 0.50) 0%, rgba(231, 243, 252, 0.50) 100%);
+  backdrop-filter: blur(8px);
+
+  .from-wrapper {
+
+    .panel-item {
+      // padding-top: 26px;
+    }
+
+    .form-item_inner {
+      padding-top: 16px;
+
+      .inner {
+        display: flex;
+        flex-wrap: nowrap;
+      }
+
+      .n-form-item {
+        width: 214px;
+        flex-shrink: 0;
+      }
+    }
+
+    .tabs {
+      @include flex(x, center, center);
+
+      .tab-item {
+        padding: 5px 16px;
+        border-radius: 100px;
+        cursor: pointer;
+      }
+
+      .tab-actvie {
+        color: #2454FF;
+        background: #EBF0FF;
+      }
+    }
+
+    .sub-title_inner {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding-bottom: 16px;
+
+      .add-btn {
+        flex-shrink: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 68px;
+        height: 30px;
+        border: 1px solid #2454FF;
+        border-radius: 4px;
+        font-size: 13px;
+        color: #2454FF;
+      }
+
+      .title {
+        width: 368px;
+        height: 30px;
+        padding-left: 10px;
+        border-radius: 4px;
+        background: linear-gradient(90deg, #F6F7F9 0%, #FFFFFF 100%);
+        line-height: 30px;
+        font-size: 14px;
+        font-weight: bold;
+        color: #1A2029;
+      }
+    }
+  }
+}
+
+/** common css **/
+.btn {
+  padding: 5px 16px;
+  text-align: center;
+  font-size: 14px;
+  font-weight: bold;
+  line-height: 22px;
+  border-radius: 4px;
+}
+
+.btn.btn_primary {
+  padding: 6px 16px;
+  background: linear-gradient(270deg, #3BD6E3 0%, #019AFE 100%);
+  color: #FFF;
+}
+
+.btn.btn_default {
+  border: 1px solid #D3D7DD;
+  background-color: #fff;
+  color: #1A2029;
+}
+
+/** reset drawer css**/
+.drawer-wrapper {
+  .n-drawer-content {
+    :deep(.drawer-body) {
+      padding: 20px;
+      background: linear-gradient(180deg, #F3F7FC 0%, #E4EAF7 100%);
+    }
+
+    :deep(.drawer-header) {
+      padding: 16px !important;
+      border: 0;
+      line-height: 24px;
+    }
+
+    :deep(.drawer-footer) {
+      justify-content: center !important;
+      align-items: center;
+      padding: 12px 24px;
+      border: 0;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.drawer-picker {
+  .el-input__wrapper {
+    height: 34px;
+    border-radius: 8px;
+    background: transparent;
+
+    .el-input__prefix {
+      display: none;
+    }
+
+    &:hover {
+      transition: all 0.3s;
+      box-shadow: 0 0 0px 1px rgba(36, 84, 255, 1);
+    }
+
+    input::focus {
+      background: red;
+    }
+  }
+
+  .el-input__wrapper.is-focus {
+    box-shadow: 0px 0px 1px 1px rgba(36, 84, 255, 1);
+  }
+}
+
+.n-drawer-mask {
+  background-color: rgba(0, 0, 0, .7);
+}
+</style>

+ 741 - 0
src/views/carbon/components/TheDrawerList.vue

@@ -0,0 +1,741 @@
+<script setup>
+import { ref, onMounted, computed } from 'vue';
+import { NDrawer, NDrawerContent, NScrollbar } from 'naive-ui';
+import { BaseCard, BasePanel } from './index';
+
+const props = defineProps(['data']);
+
+let cardNodelist = [];
+
+const isVisibleDrawer = defineModel(false);
+
+const tabActive = ref(0);
+const tabList = ['基础信息', '污水处理', '能源药剂', '污泥处理', '替碳碳汇'];
+const scrollRef = ref(null);
+
+const rslxEnum = {
+  0: '半连续-加煤机',
+  1: '半连续-流化床',
+  2: '间歇性-加煤机',
+  3: '间歇性-流化床',
+  4: '连续燃烧'
+}
+
+const wnrjQtLxEnum = {
+  0: '竖井类型',
+  1: '流化床式',
+  2: '回转窑式'
+}
+
+const scgmEnum = {
+  0: '小型',
+  1: '中型',
+  2: '大型'
+}
+
+const list = computed(() => {
+
+  let sewageOneList = [];
+  let energyOneList = [];
+  let energyTwoList = [];
+  let carbonOneList = [];
+  let carbonTwoList = [];
+  let carbonThreeList = [];
+
+  if ( Object.keys(props.data).length ) {
+    sewageOneList = props.data.extraMap['0'] || [];
+    energyOneList = props.data.extraMap['1'] || [];
+    energyTwoList = props.data.extraMap['2'] || [];
+    carbonOneList = props.data.extraMap['3'] || [];
+    carbonTwoList = props.data.extraMap['4'] || [];
+    carbonThreeList = props.data.extraMap['5'] || [];
+  }
+
+  return {
+    sewageOneList,
+    energyOneList,
+    energyTwoList,
+    carbonOneList,
+    carbonTwoList,
+    carbonThreeList
+  }
+})
+
+const handleTabItem = (index) => {
+  const top = cardNodelist[index]?.offsetTop;
+  scrollRef.value.scrollTo({
+    top,
+    behavior: 'smooth'
+  })
+  tabActive.value = index;
+}
+
+const onAfterdEnter = () => {
+  console.log('onAfterdEnter');
+}
+
+onMounted(() => {
+  cardNodelist = document.querySelectorAll(".card-wrapper");
+})
+
+</script>
+
+<template>
+  <NDrawer :width="1220" placement="right" v-model:show="isVisibleDrawer" class="drawer-wrapper" :on-after-enter="onAfterdEnter">
+    <n-drawer-content closable title="历史核算" header-class="drawer-header" body-content-class="drawer-body" footer-class="drawer-footer">
+
+      <div class="main-container">
+        <div class="header">
+          <ul class="tab-list space-x-[4px]">
+            <li
+              v-for="item, index in tabList"
+              :key="item"
+              :class="['tab-item', { active: tabActive === index }]"
+              @click="handleTabItem(index)"
+            >{{ item }}</li>
+          </ul>
+          <button class="btn">下载核算结果</button>
+        </div>
+        <div class="content">
+          <NScrollbar style="height: 100%" :on-scroll="onScroll" ref="scrollRef">
+            <div class="main space-y-[12px]">
+              <BaseCard title="基础信息" sub-title="碳排放管理基础信息填写">
+                <ul class="list-info">
+                  <li class="item space-x-[10px]">
+                    <span class="label">省/直辖市</span>
+                    <span class="value">{{ data.provinceName }}</span>
+                  </li>
+                  <li class="item space-x-[10px]">
+                    <span class="label">核算时间</span>
+                    <span class="value">{{ data.addYearMonth }}</span>
+                  </li>
+                </ul>
+              </BaseCard>
+
+              <BaseCard title="污水处理" sub-title="生化反应碳排">
+                <BasePanel isNoPadding title="石源碳矿化产生的碳排放量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">月处理水量</span>
+                      <span class="value">{{ data.wsHsytkhClsl }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">进水COD</span>
+                      <span class="value">{{ data.wsHsytkhJsCod }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">出水COD</span>
+                      <span class="value">{{ data.wsHsytkhCsCod }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">化石源的CO₂排放量</span>
+                      <span class="value blue">{{ data.wsHsytkhCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="外加碳源矿化产生的化石源CO₂碳排放量" class="space-y-[14px]">
+                  <ul class="list-info" v-for="item in list.sewageOneList">
+                    <li class="item space-x-[10px]">
+                      <span class="label">碳源名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">外加碳源用量</span>
+                      <span class="value">{{ item.amount }} (Kg/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">外加碳源的化石源CO₂排放量</span>
+                      <span class="value blue">{{ val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                  <!-- <div class="line"></div> -->
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">碳源名称</span>
+                      <span class="value bold">葡萄糖</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">外加碳源用量</span>
+                      <span class="value">200 (Kg/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">外加碳源的化石源CO₂排放量</span>
+                      <span class="value blue">100 (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污水收集提升和处理阶段排放的CH₄的CO₂当量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">泵站和沉砂池逸散的CH₄量</span>
+                      <span class="value">{{ data.wsSjclCh4Tsb ? '实测' : '未实测' }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">月处理水量</span>
+                      <span class="value">{{ data.wsSjclCh4Clsl }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">进水COD</span>
+                      <span class="value">{{ data.wsSjclCh4JsCod }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">出水COD</span>
+                      <span class="value">{{ data.wsSjclCh4CsCod }}  (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水处理阶段CH₄的排放因子</span>
+                      <span class="value">{{ data.wsSjclCh4Pfyz }}  (kg CH₄/kg COD)</span>
+                    </li>
+
+                    <li class="item space-x-[10px]" v-if="data.wsSjclCh4Tsb">
+                      <span class="label">提升泵逸散的CH₄量</span>
+                      <span class="value">{{ data.wsSjclCh4Tsb }} (kg/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]" v-if="data.wsSjclCh4Csc">
+                      <span class="label">沉砂池逸散的CH₄量</span>
+                      <span class="value">{{ data.wsSjclCh4Csc }}  (kg/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水处理阶段排放的CH₄的CO₂当量</span>
+                      <span class="value blue">{{ data.wsSjclCh4Co2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污水生物处理脱氮过程排放的N₂O的CO₂当量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">月处理水量</span>
+                      <span class="value">{{ data.wsTdN2oClsl }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">进水TN</span>
+                      <span class="value">{{ data.wsTdN2oJsTn }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">出水TN</span>
+                      <span class="value">{{ data.wsTdN2oCsTn }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水处理阶段N₂O的排放因子</span>
+                      <span class="value">{{ data.wsTdN2oPfyz }} (kg N₂O-N/kg N)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水处理阶段排放的N₂O的CO₂当量</span>
+                      <span class="value blue">{{ data.wsTdN2oCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+              </BaseCard>
+
+              <BaseCard title="能源、药剂碳排" sub-title="生化反应碳排">
+                <BasePanel isNoPadding title="污水厂电力消耗产生的碳排放量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">总耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhZhdl }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水厂电力消耗产生的总碳排放量</span>
+                      <span class="value blue">{{ data.nyyjDlxhZhdlCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">进水泵房电量</span>
+                      <span class="value">{{ data.nyyjDlxhJsbf }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">进水泵房碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhJsbfCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">鼓风机房电量</span>
+                      <span class="value">{{ data.nyyjDlxhGfjf }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">鼓风机房碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhGfjfCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">脱水机房电量</span>
+                      <span class="value">{{ data.nyyjDlxhTsjf }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">脱水机房碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhTsjfCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">消毒间耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhXdj }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">消毒间碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhXdjCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">深度处理用电耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhSdcl }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">深度处理用电碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhSdclCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥处置用电耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhWncz }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥处置用电碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhWnczCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">生活区耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhShq }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">生活区碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhShqCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">其他耗电量</span>
+                      <span class="value">{{ data.nyyjDlxhQt }} (kW·h/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">其他碳排</span>
+                      <span class="value blue">{{ data.nyyjDlxhQtCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="净购入热力消耗产生的碳排放量" class="space-y-[14px]">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">蒸汽</span>
+                      <span class="value bold">{{ data.nyyjGrrlZq }} (t/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">对应焓值</span>
+                      <span class="value">{{data.nyyjGrrlDyhz}} (KJ/Kg)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">热力</span>
+                      <span class="value">{{ data.nyyjGrrlRl }} (GJ/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料消耗产生的碳排放量</span>
+                      <span class="value blue">{{ data.nyyjGrrlCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="固定式能源燃料消耗产生的碳排放量">
+                  <ul class="list-info" v-for="item, index in list.energyOneList" :key="index">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料消耗量</span>
+                      <span class="value">{{ item.amount }} (t/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料消耗产生的碳排放量</span>
+                      <span class="value blue">{{ item.val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污水处理阶段药剂消耗产生的碳排放量">
+                  <ul class="list-info" v-for="item, index in list.energyTwoList" :key="index">
+                    <li class="item space-x-[10px]">
+                      <span class="label">药剂名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">药剂消耗量</span>
+                      <span class="value">{{ item.amount }} (t/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料消耗产生的碳排放量</span>
+                      <span class="value blue">{{ item.val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+              </BaseCard>
+
+              <BaseCard title="污泥处理" sub-title="生化反应碳排">
+                <BasePanel isNoPadding title="污泥厌氧消化沼气收集管路无意泄露的CH₄或沼气火炬燃烧不充分导致的碳排放">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼气产量</span>
+                      <span class="value">{{ data.wnclYyzqZqcl }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼气中CH的质量分数</span>
+                      <span class="value">{{ data.wnclYyzqChZlfs }} (%)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥厌氧消化过程排放的CH₄的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclYyzqCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="单独处理污泥厌氧消化过程产生的碳排放量" class="space-y-[14px]">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼液处理量</span>
+                      <span class="value bold">{{ data.wnclDdclZycll }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼液处理前TN浓度</span>
+                      <span class="value">{{ data.wnclDdclClqnd }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼液处理后TN浓度</span>
+                      <span class="value">{{ data.wnclDdclClhnd }} (mg/L)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">处理阶段N₂O的排放因子</span>
+                      <span class="value">{{ data.wnclDdclPfyz }} (kg N₂O-N/kg N)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">单独处理污泥厌氧消化产生沼液的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclDdclCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥好氧发酵过程生化反应的碳排放">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥处理好氧发酵量</span>
+                      <span class="value">{{ data.wnclHyfjFjl }} kg干污泥/月</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥好氧发酵过程排放的CH₄的CO₂当量</span>
+                      <span class="value">{{ data.wnclHyfjCh4Co2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥好氧发酵过程排放的N₂O的CO₂当量</span>
+                      <span class="value">{{ data.wnclHyfjN2oCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥干化焚烧或协同焚烧过程,化石源碳被氧化产生的化石源CO₂碳排放量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料消耗量</span>
+                      <span class="value bold">{{ data.wnclWnfsXhl }} (m3/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥干物质中含碳比例</span>
+                      <span class="value">{{ data.wnclWnfsHtbl }} (%)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥好氧发酵过程排放的CH₄的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclWnfsCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥焚烧过程不完全燃烧产生的CH₄和N₂O的CO₂排放当量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃烧类型</span>
+                      <span class="value bold">{{ rslxEnum[data.wnclBwqrsRslx] }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥处理焚烧量</span>
+                      <span class="value">{{ data.wnclBwqrsFsl }} (t干污泥/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧过程N₂O的排放因子</span>
+                      <span class="value">{{ data.wnclBwqrsPfyz }} (kg N₂O/t 干污泥)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧过程排放的CH₄的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclBwqrsCh4Co2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧过程排放的N₂O的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclBwqrsN2oCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥热解碳化或气化过程化石源CO">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解消耗量</span>
+                      <span class="value">{{ data.wnclWnrjByhXhl }} (kg干污泥/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥干物质中含碳比例</span>
+                      <span class="value">{{ data.wnclWnrjByhHtbl }} (%)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解过程排放的CH₄的CO₂当量</span>
+                      <span class="value">{{ data.wnclWnrjByhCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥热解碳化或气化过程产生的CH₄和N₂O的CO₂排放当量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">反应堆类型</span>
+                      <span class="value">{{ wnrjQtLxEnum[data.wnclWnrjQtLx] }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解消耗量</span>
+                      <span class="value">{{ data.wnclWnrjQtXhl }} (t干污泥/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解过程N₂O的排放因子</span>
+                      <span class="value">{{ data.wnclWnrjQtPfyz }} (kg N₂O/t 干污泥)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解过程排放的CH₄的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclWnrjQtCh4Co2 }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥热解过程排放的N₂O的CO₂当量</span>
+                      <span class="value blue">{{ data.wnclWnrjQtN2oCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+              </BaseCard>
+
+              <BaseCard title="替碳、碳汇" sub-title="111111">
+                <BasePanel isNoPadding title="热泵技术-替碳量">
+                  <ul class="list-info" v-for="item, index in list.carbonOneList" :key="index">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污水厂电力消耗产生的总碳排放量</span>
+                      <span class="value blue">{{ item.amount }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">热泵替碳量</span>
+                      <span class="value blue">{{ item.val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="光伏-替碳量" class="space-y-[14px]">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">总耗电量</span>
+                      <span class="value bold">{{ data.thGfZhdl }} (t/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">光伏发电替碳量</span>
+                      <span class="value blue">{{data.thGfCo2}} (KJ/Kg)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="再生水回用的替碳量(宜按替代的商业供水的取水、生产和输送的碳排放量计算)">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">水厂规模</span>
+                      <span class="value">{{ scgmEnum[data.thZssScgm] }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">回用水供应量 </span>
+                      <span class="value">{{ data.thZssGyl }} (m³/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">回用水替代供水的替碳量</span>
+                      <span class="value blue">{{ data.thZssCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥厌氧消化沼气利用的替碳量">
+                  <ul class="list-info" v-for="item in list.carbonTwoList" :key="index">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥厌氧消化沼气发电量</span>
+                      <span class="value">{{ item.amount }} (t/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">厌氧消化沼气富余热能利用量</span>
+                      <span class="value">{{ item.lyl }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">沼气提纯并网的天然气量</span>
+                      <span class="value">{{ item.hz }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥厌氧消化沼气利用的替碳量</span>
+                      <span class="value blue">{{ item.val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥焚烧或热解热能利用的替碳量">
+                  <ul class="list-info" v-for="item in list.carbonThreeList" :key="index">
+                    <li class="item space-x-[10px]">
+                      <span class="label">燃料名称</span>
+                      <span class="value bold">{{ item.dictLabel }}</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧或热解的电力利用量</span>
+                      <span class="value">{{ item.amount }} (kW·h/d)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧或热解热能利用量</span>
+                      <span class="value blue">{{ item.lyl }} (t CO₂-eq/月)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">对应焓值</span>
+                      <span class="value blue">{{ item.hz }} (KJ/Kg)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥焚烧或热解热能利用的替碳量</span>
+                      <span class="value blue">{{ item.val }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+                <BasePanel isNoPadding title="污泥经过厌氧、好氧或碳化处理后,产生的替碳量">
+                  <ul class="list-info">
+                    <li class="item space-x-[10px]">
+                      <span class="label">回收作为肥料的污泥量</span>
+                      <span class="value bold">{{ data.thWnClhFlwnl }} (kg 干污泥/d)</span>
+                    </li>
+                    <li class="item space-x-[10px]">
+                      <span class="label">污泥产物土地利用的替碳量</span>
+                      <span class="value">{{ data.thWnClhCo2 }} (t CO₂-eq/月)</span>
+                    </li>
+                  </ul>
+                </BasePanel>
+              </BaseCard>
+            </div>
+          </NScrollbar>
+        </div>
+      </div>
+    </n-drawer-content>
+  </NDrawer>
+</template>
+
+<style lang="scss" scoped>
+.main-container {
+  display: flex;
+  flex-flow: column;
+  height: 100%;
+  padding: 21px 24px;
+  border-radius: 20px;
+  border: 1px solid #FFF;
+  background: linear-gradient(180deg, rgba(238, 253, 255, 0.50) 0%, rgba(231, 243, 252, 0.50) 100%);
+  backdrop-filter: blur(8px);
+
+  .header {
+    flex-shrink: 0;
+    @include flex(x, center, between);
+    padding: 12px 16px;
+    border-radius: 10px;
+    background: #fff;
+    
+    .btn {
+      border-radius: 4px;
+      padding: 5px 16px;
+      background: #2454FF;
+      font-size: 14px;
+      line-height: 22px;
+      text-align: left;
+      color: #fff
+    }
+
+    .tab-list {
+      @include flex(x, center, center);
+      text-align: center;
+      font-size: 14px;
+      line-height: 22px;
+      color: #1A2029;
+
+      .tab-item {
+        padding: 9px 24px;
+        cursor: pointer;
+      }
+
+      .active {
+        border-radius: 3px;
+        background: #EBF0FF;
+        color: #2454FF;
+        font-weight: bold;
+      }
+    }
+  }
+
+  .content {
+    height: calc(100% - 76px);
+    margin-top: 12px;
+    
+    .main {
+
+      .line {
+        height: 1px;
+        padding: 0 100px;
+        margin: 16px 0;
+        background: #EBF0FF;
+      }
+
+      .list-info {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: flex-end;
+        .item {
+          display: flex;
+          width: 50%;
+          font-size: 14px;
+          line-height: 32px;
+
+          .label {
+            width: 260px;
+            text-align: right;
+            color: #86909C;
+          }
+
+          .value {
+            text-align: left;
+          }
+
+          .blue {
+            color: #3A93FF;
+          }
+
+          .bold {
+            font-weight: bold;
+          }
+        }
+      }
+    }
+  }
+}
+
+.card {
+  padding: 20px 16px;
+  border-radius: 10px;
+  background: #fff;
+}
+
+/** reset drawer css**/
+.drawer-wrapper {
+  .n-drawer-content {
+    :deep(.drawer-body) {
+      padding: 20px;
+      background: linear-gradient(180deg, #F3F7FC 0%, #E4EAF7 100%);
+    }
+    :deep(.drawer-header) {
+      padding: 16px !important;
+      border: 0;
+      line-height: 24px;
+    }
+    :deep(.drawer-footer) {
+      justify-content: center !important;
+      align-items: center;
+      padding: 12px 24px;
+      border: 0;
+    }
+  }
+}
+</style>
+
+<style>
+.n-drawer-mask {
+  background-color: rgba(0, 0, 0, .7);
+}
+</style>

+ 158 - 0
src/views/carbon/components/TheModal.vue

@@ -0,0 +1,158 @@
+<script setup>
+import { ref, h } from 'vue';
+import { NModal, NForm, NGrid, NFormItemGi, NInput, NDatePicker, NPagination, NDataTable } from 'naive-ui';
+
+const showModal = ref(true);
+const inputThemeOverrides = {
+  border: '1px solid #d7d9e5',
+  borderRadius: '8px',
+  borderHover: '1px solid #2454FF',
+  borderFocus: '1px solid #2454FF',
+  boxShadowFocus: '0 0 0 2px rgba(36, 84, 255, 0.2)',
+  text: '#333'
+}
+
+const selectThmem = {
+  peers: {
+    Input: {
+      border: '1px solid #d7d9e5',
+      borderRadius: '8px',
+      borderHover: '1px solid #2454FF',
+      borderFocus: '1px solid #2454FF',
+      boxShadowFocus: '0 0 0 2px rgba(36, 84, 255, 0.2)',
+      text: '#333'
+    }
+  }
+}
+
+const range = ref(null);
+
+const columns = [
+  { title: '核算日期', key: 'name1', align: 'center' },
+  { title: '总碳排放量', key: 'name2', align: 'center' },
+  { title: '污水处理碳排放量', key: 'name3', align: 'center' },
+  { title: '能源、药剂碳排量', key: 'name4', align: 'center' },
+  { title: '污泥处理碳排量', key: 'name5', align: 'center' },
+  { title: '替碳、碳汇替碳量', key: 'name6', align: 'center' },
+  { title: '录入人员', key: 'name7', align: 'center' },
+  { title: '填报日期', key: 'name8', align: 'center' },
+  { title: '操作', key: 'name9', align: 'center', render: (row) => {
+    return h('span', {
+      class: 'text-[#2454FF] cursor-pointer',
+      onClick: () => {
+        console.log(row);
+      }
+    }, '下载');
+  }}
+]
+
+const page = ref(1);
+
+const data = ref([
+  { name1: 1, name2: 1 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 },
+  { name2: 2 }
+]);
+
+</script>
+
+<template>
+  <NModal
+    v-model:show="showModal"
+    preset="card"
+    class="custom-card"
+    title="历史核算"
+    header-class="card-preset_header"
+    content-class="card-prset_content"
+    :style="{ width: '1440px' }"
+    :bordered="false"
+  >
+    <div class="main-container space-y-[12px]">
+      <div class="search-inner">
+        <NForm :show-feedback="false">
+          <NGrid :cols="14" :x-gap="24">
+            <NFormItemGi :span="4" label="录入人员:" path="adress" label-placement="top">
+              <NInput :theme-overrides="inputThemeOverrides"/>
+            </NFormItemGi>
+            <NFormItemGi :span="4" label="填报日期:" path="adress" label-placement="top">
+              <n-date-picker v-model:value="range" type="daterange" clearable :theme-overrides="selectThmem"/>
+            </NFormItemGi>
+            <NFormItemGi :span="4" label="核算日期:" path="adress" label-placement="top">
+              <n-date-picker v-model:value="range" type="daterange" clearable :theme-overrides="selectThmem"/>
+            </NFormItemGi>
+            <NFormItemGi :span="2" label="" path="adress" label-placement="top">
+              <div class="space-x-[10px]">
+                <button class="btn">查询</button>
+                <button class="btn default">重置</button>
+              </div>
+            </NFormItemGi>
+          </NGrid>
+        </NForm>
+      </div>
+
+      <div class="table-inner">
+        <NDataTable :columns="columns" :data="data" :bordered="false" :single-line="false" :min-height="400" :max-height="400"></NDataTable>
+        <div class="pt-[20px] flex justify-center">
+          <NPagination v-model:page="page" :page-count="100"></NPagination>
+        </div>
+      </div>
+    </div>
+  </NModal>
+</template>
+
+<style lang="scss" scoped>
+.main-container {
+  padding: 20px;
+  border-radius: 20px;
+  border: 1px solid #FFFFFF;
+  background: linear-gradient(180deg, rgba(238, 253, 255, 0.5) 0%, rgba(231, 243, 252, 0.5) 100%);
+
+  .search-inner, .table-inner {
+    padding: 20px 20px;
+    border-radius: 10px;
+    background: #fff;
+
+    .btn {
+      border-radius: 4px;
+      padding: 5px 16px;
+      background: #2454FF;
+      font-size: 14px;
+      line-height: 22px;
+      text-align: left;
+      color: #fff;
+    }
+
+    .default {
+      border: 1px solid #d7d9e5;
+      color: #2454FF;
+      background: #fff;
+    }
+  }
+
+  .table-inner {
+
+  }
+}
+</style>
+
+<style lang="scss">
+.card-preset_header {
+  padding: 16px !important;
+}
+.card-prset_content {
+  padding: 20px !important;
+  background: linear-gradient(180deg, #F3F7FC 0%, #E4EAF7 100%);
+}
+</style>

+ 72 - 0
src/views/carbon/components/config.js

@@ -0,0 +1,72 @@
+export const inputConfig = {
+  sewage: {
+    oneBlock: [
+      { label: '月处理水量', unit: 'm³/月', key: 'wsHsytkhClsl' },
+      { label: '进水COD', unit: 'mg/L', key: 'wsHsytkhJsCod' },
+      { label: '出水COD', unit: 'mg/L', key: 'wsHsytkhCsCod' }
+    ],
+    twoBlock: [
+      { label: '月处理水量', unit: 'm³/月', key: 'wsSjclCh4Clsl' },
+      { label: '进水COD', unit: 'mg/L', key: 'wsSjclCh4JsCod' },
+      { label: '出水COD*', unit: 'mg/L', key: 'wsSjclCh4CsCod' },
+      { label: '污水处理阶段CH₄的排放因子', unit: 'kg CH₄/kg COD', key: 'wsSjclCh4Pfyz' },
+      { label: '提升泵逸散的CH₄量', unit: 'kg/月', key: 'wsSjclCh4Tsb' },
+      { label: '沉砂池逸散的CH₄量', unit: 'kg/月', key: 'wsSjclCh4Csc' }
+    ],
+    threeBlock: [
+      { label: '月处理水量', unit: 'm³/月', key: 'wsTdN2oClsl' },
+      { label: '进水TN', unit: 'mg/L', key: 'wsTdN2oJsTn' },
+      { label: '出水TN*', unit: 'mg/L', key: 'wsTdN2oCsTn' },
+      { label: '污水处理阶段N₂O的排放因子', unit: 'kg CH₄/kg COD', key: 'wsTdN2oPfyz' },
+    ]
+  },
+  energy: {
+    oneBlock: [
+      { label: '总耗电量', unit: 'kW·h/月', key: 'nyyjDlxhZhdl' },
+      { label: '进水泵房电量', unit: 'kW·h/月', key: 'nyyjDlxhJsbf' },
+      { label: '鼓风机房电量', unit: 'kW·h/月', key: 'nyyjDlxhGfjf' },
+      { label: '脱水机房电量', unit: 'kW·h/月', key: 'nyyjDlxhTsjf' },
+      { label: '消毒间耗电量', unit: 'kW·h/月', key: 'nyyjDlxhXdj' },
+      { label: '深度处理用电耗电量', unit: 'kW·h/月', key: 'nyyjDlxhSdcl' },
+      { label: '污泥处置用电耗电量', unit: 'kW·h/月', key: 'nyyjDlxhWncz' },
+      { label: '生活区耗电量', unit: 'kW·h/月', key: 'nyyjDlxhShq' },
+      { label: '其他耗电量', unit: 'kW·h/月', key: 'nyyjDlxhQt' }
+    ],
+    twoBlock: [
+      { label: '蒸汽', unit: 't/月', key: 'nyyjGrrlZq' },
+      { label: '对应焓值', unit: 'KJ/Kg', key: 'nyyjGrrlDyhz' },
+      { label: '热力', unit: 'GJ/月', key: 'nyyjGrrlRl' },
+    ]
+  },
+  sludge: {
+    oneBlock: [
+      { label: '沼气产量', unit: 'm³/月', key: 'wnclYyzqZqcl' },
+      { label: '沼气中CH的质量分数 ', unit: '%', key: 'wnclYyzqChZlfs' },
+    ],
+    twoBlock: [
+      { label: '沼液处理量', unit: 'm³/月', key: 'wnclDdclZycll' },
+      { label: '沼液处理前TN浓度 ', unit: 'mg/L', key: 'wnclDdclClqnd' },
+      { label: '沼液处理后TN浓度 ', unit: 'mg/L', key: 'wnclDdclClhnd' },
+      { label: '处理阶段N₂O的排放因子 ', unit: 'kg N₂O-N/kg N', key: 'wnclDdclPfyz' },
+    ],
+    threeBlock: [
+      { label: '污泥处理好氧发酵量', unit: 'kg干污泥/月', key: 'wnclHyfjFjl' },
+    ],
+    fourBlock: [
+      { label: '污泥处理焚烧量', unit: 'kg干污泥/月', key: 'wnclWnfsXhl' },
+      { label: '污泥干物质中含碳比例', unit: '%', key: 'wnclWnfsHtbl' },
+    ],
+    fiveBlock: [
+      { label: '污泥热解消耗量', unit: 'kg干污泥/月', key: 'wnclWnrjByhXhl' },
+      { label: '污泥干物质中含碳比例 ', unit: '%', key: 'wnclWnrjByhHtbl' },
+    ],
+  },
+  carbon: {
+    oneBlock: [
+      { label: '总耗电量 ', unit: 'kW·h/月', key: 'thGfZhdl' }
+    ],
+    twoBlock: [
+      { label: '回收作为肥料的污泥量', unit: 'kg 干污泥/d', key: 'thWnClhFlwnl' }
+    ]
+  }
+}

+ 21 - 0
src/views/carbon/components/index.js

@@ -0,0 +1,21 @@
+import BaseCard from './BaseCard.vue';
+import BaseStep from './BaseStep.vue';
+import BaseTable from './BaseTable.vue';
+import BasePanel from './BasePanel.vue';
+
+import TheDrawerForm from './TheDrawerForm.vue';
+import TheDrawerList from './TheDrawerList.vue';
+import TheModal from './TheModal.vue';
+
+import BaseDatePicker from './BaseDatePicker.vue';
+
+export {
+  BaseCard,
+  BaseStep,
+  BaseTable,
+  BasePanel,
+  BaseDatePicker,
+  TheDrawerForm,
+  TheDrawerList,
+  TheModal
+}

+ 247 - 0
src/views/carbon/components/screen/DataBorad.vue

@@ -0,0 +1,247 @@
+<script setup>
+import { ref, computed } from 'vue';
+
+const props = defineProps({
+  data: {
+    type: Object,
+    required: {}
+  }
+})
+
+const avgEnum = {
+  "-1" : "低于",
+  "0"  : "持平",
+  "1"  : "高于"
+}
+
+const boardList = ref([
+  {
+    label: '总碳排放量',
+    key: 'ztTotalCo2',
+    hbKey: 'ztTotalCo2Hb',
+    desc: '环比上月',
+    unit: 't CO₂-eq',
+    value: ''
+  },
+  {
+    label: '污水厂行业碳排放强度',
+    key: 'wschytpfqd',
+    hbKey: 'wschytpfqdHb',
+    strong: true,
+    desc: '同行业平均水平',
+    unit: 'Kg CO₂-eq/m³',
+    value: ''
+  },
+  {
+    label: '替碳、碳汇',
+    key: 'ttthTotalCo2',
+    hbKey: 'ttthTotalCo2Hb',
+    desc: '环比上月',
+    unit: 't CO₂-eq',
+    value: ''
+  },
+  {
+    label: '污水 - 生化反应',
+    key: 'wsclTotalCo2',
+    hbKey: 'wsclTotalCo2Hb',
+    desc: '环比上月',
+    unit: 't CO₂-eq',
+    value: ''
+  },
+  {
+    label: '能源、药剂',
+    key: 'nyyjTotalCo2',
+    hbKey: 'nyyjTotalCo2Hb',
+    desc: '环比上月',
+    unit: 't CO₂-eq',
+    value: ''
+  },
+  {
+    label: '污泥 - 生化反应',
+    key: 'wnclTotalCo2',
+    hbKey: 'wnclTotalCo2Hb',
+    desc: '环比上月',
+    unit: 't CO₂-eq',
+    value: ''
+  },
+]);
+
+const list111 = computed(() => {
+  boardList.value.map(item => {
+
+    Object.entries(props.data).forEach(([k, v]) => {
+     
+      if ( item.key === k ) {
+        item.value = v
+      }
+
+      // if () {
+
+      // }
+
+    })
+    console.log("item", item);
+
+  })
+})
+
+// 总碳排放量
+
+</script>
+
+<template>
+  <div class="data-board-view">
+    <div class="board-item" v-for="item, index in boardList" :key="item.key">
+      <p class="title">{{ item.label }}</p>
+      
+      <p class="statement">
+        <span class="num">{{ data[item.key] }} </span>
+        <span class="unit"> {{ item.unit }}</span>
+      </p>
+      <div class="info-wrapper">
+        <p class="desc">
+          <span v-if="item.strong">
+            <strong class="text-[#e5773f]">{{ avgEnum[data.exceedAvgHY] }}</strong>
+            <span>{{ item.desc }}</span>
+          </span>
+          <span v-else>{{ item.desc }}</span>
+        </p>
+        <p :class="['info', 'space-x-[5px]', { down: data[item.hbKey] < 0 }]" v-if="index !== 1">
+          <span class="num">{{ data[item.hbKey] ?? '-'}} %</span>
+          <span class="icon" v-if="data[item.hbKey]"></span>
+        </p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+
+@mixin bg-img ($url) {
+  background: url($url) 80% 10% no-repeat,
+  url("@/assets/images/carbon/bg-board-bottom.png") center bottom no-repeat,
+  url("@/assets/images/carbon/bg-board-right.png") right bottom no-repeat,
+  linear-gradient(180deg, #0C1E3C 0%, #132B51 100%);
+}
+
+.data-board-view {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  grid-template-rows: repeat(2, 1fr);
+  grid-gap: 20px;
+
+  .board-item {
+    position: relative;
+    @include flex(y, start, between);
+    padding: 50px 0 10px 20px;
+    border-radius: 8px;
+
+    &:nth-child(1) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-one.svg");
+      background-size: auto, 100%;
+    }
+    &:nth-child(2) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-two.svg");
+      background-size: auto, 100%;
+    }
+    &:nth-child(3) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-three.svg");
+      background-size: auto, 100%;
+    }
+    &:nth-child(4) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-four.svg");
+      background-size: auto, 100%;
+    }
+    &:nth-child(5) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-five.svg");
+      background-size: auto, 100%;
+    }
+    &:nth-child(6) {
+      @include bg-img("@/assets/images/carbon/svg/icon-borad-six.svg");
+      background-size: auto, 100%;
+    }
+
+    &::after, &::before {
+      content: ' ';
+      position: absolute;
+      left: -2px;
+      display: block;
+      width: calc(100% + 4px);
+      height: 18px;
+    }
+
+    &::before {
+      top: 0px;
+      background: url("@/assets/images/carbon/svg/icon-top-left.svg") left center no-repeat,
+      url("@/assets/images/carbon/svg/icon-top-right.svg") right center no-repeat;
+    }
+
+    &::after {
+      bottom: 0px;
+      background: url("@/assets/images/carbon/svg/icon-bottom-left.svg") left center no-repeat,
+      url("@/assets/images/carbon/svg/icon-bottom-right.svg") right center no-repeat;
+    }
+
+    .title {
+      height: 40px;
+      font-size: 14px;
+      line-height: 20px;
+      color: #fff;
+    }
+
+    &:nth-child(2) {
+      .title {
+        width: 80px;
+      }
+    }
+
+    .statement {
+      color: #FFF;
+      text-shadow: 0px 0px 6.3px #C9FDF3;
+      .num {
+        line-height: 20px;
+        font-family: 'D-DIN-PRO-700-Bold';
+        font-size: 32px;
+        font-weight: bold;
+      }
+      .unit {
+        font-size: 12px;
+      }
+    }
+
+    .info-wrapper {
+      height: 38px;
+      line-height: 16px;
+      .desc {
+        line-height: 22px;
+        color: rgba(255, 255, 255, 0.5);
+      }
+    }
+
+    .info {
+      @include flex(x, center, start);
+      .num {
+        font-family: 'D-DIN-PRO-700-Bold';
+        font-size: 18px;
+        font-weight: bold;
+        color: rgba(0, 255, 0, 1);
+      }
+      .icon {
+        width: 14px;
+        height: 8px;
+        background: url('@/assets/images/carbon/svg/icon-up.svg') no-repeat;
+      }
+    }
+
+    .down {
+      .num {
+        color: #e9672c;
+      }
+      .icon {
+        background: url('@/assets/images/carbon/svg/icon-down.svg') no-repeat;
+        transform: rotate(60deg);
+      }
+    }
+  }
+}
+</style>

+ 119 - 0
src/views/carbon/components/screen/DataScroll.vue

@@ -0,0 +1,119 @@
+<script setup>
+import { ref } from 'vue';
+import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'
+import LayoutCard from './LayoutCard.vue'
+
+const listData = ref([{
+  'title': '无缝滚动第一行无缝滚动第一行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第二行无缝滚动第二行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第三行无缝滚动第三行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第四行无缝滚动第四行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第五行无缝滚动第五行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第六行无缝滚动第六行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第七行无缝滚动第七行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第八行无缝滚动第八行',
+  'date': '2017-12-16'
+}, {
+  'title': '无缝滚动第九行无缝滚动第九行',
+  'date': '2017-12-16'
+}])
+
+defineProps({
+  data: {
+    type: Array,
+    default: () => []
+  }
+})
+
+console.log(listData);
+const start = ref(false)
+</script>
+
+<template>
+  <LayoutCard title="数据指标汇总" isLarge>
+    <div class="scroll-container">
+      <ul class="header">
+        <li>名称</li>
+        <li>碳排放</li>
+      </ul>
+      <div class="main">
+        <vue3-seamless-scroll :list="data" class="scroll" hover :singleHeight="40" :singleWaitTime="3000">
+          <ul class="item" v-for="(item, index) in data" :key="index">
+            <li>{{ item.label }}(t CO₂-eq/月)</li>
+            <li>{{ item.value }}</li>
+          </ul>
+        </vue3-seamless-scroll>
+      </div>
+    </div>
+  </LayoutCard>
+</template>
+
+<style lang="scss" scoped>
+.scroll-container {
+  height: 100%;
+  padding: 30px 30px;
+  line-height: 40px;
+  font-size: 14px;
+  color: #fff;
+
+  .header, .item {
+    display: flex;
+    height: 40px;
+    background: rgba(13, 80, 135, 0.8);
+
+    & li:nth-child(1){
+      padding: 0 10px 0 46px;
+      width: 75%;
+      overflow:hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      -o-text-overflow:ellipsis;
+    }
+
+    & li:nth-child(2) {
+      width: 25%;
+    }
+  }
+
+  .main {
+    height: calc(100% - 40px);
+    overflow: hidden;
+
+    .scroll {
+      width: 100%;
+      height: 100%;
+      overflow: hidden;
+    }
+
+    .item:nth-child(1n) {
+      background: transparent;
+    }
+    .item:nth-child(2n) {
+      background: rgba(97, 163, 217, 0.2);
+    }
+
+  }
+}
+
+
+.scroll .item {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 3px 0;
+}
+</style>

+ 29 - 0
src/views/carbon/components/screen/EchartColumnar.vue

@@ -0,0 +1,29 @@
+<script setup>
+import { ref, onMounted } from 'vue';
+import * as echarts from 'echarts';
+import LayoutCard from './LayoutCard';
+
+import { echartColumnarOptions } from '../../echartOptions';
+
+const echartRef = ref(null);
+
+onMounted(() => {
+  const chart = echarts.init(echartRef.value, 'light');
+  chart.setOption( echartColumnarOptions() );
+})
+</script>
+
+<template>
+  <LayoutCard title="123123">
+    <div class="echart-inner w-full h-full">
+      <div ref="echartRef" class="w-full h-full"></div>
+    </div>
+  </LayoutCard>
+</template>
+
+<style scoped>
+.echart-inner {
+  /* width: 100%; */
+  /* height: 1000px; */
+}
+</style>

+ 29 - 0
src/views/carbon/components/screen/EchartEnergy.vue

@@ -0,0 +1,29 @@
+<script setup>
+import { ref, onMounted } from 'vue';
+import * as echarts from 'echarts';
+import LayoutCard from './LayoutCard';
+
+import { echart3DOptions } from '../../echartOptions';
+
+const echartRef = ref(null);
+
+onMounted(() => {
+  const chart = echarts.init(echartRef.value, 'light');
+  chart.setOption( echart3DOptions() )
+})
+</script>
+
+<template>
+  <LayoutCard title="能源、药剂">
+    <div class="echart-inner w-full h-full">
+      <div ref="echartRef" class="w-full h-full"></div>
+    </div>
+  </LayoutCard>
+</template>
+
+<style lang="scss" scoped>
+.echart-inner {
+  font-family: 'D-DIN-PRO-700-Bold';
+  background: url('@/assets/images/carbon/bg-3d.png') 18% 70% no-repeat;
+}
+</style>

+ 13 - 0
src/views/carbon/components/screen/EchartSewage.vue

@@ -0,0 +1,13 @@
+<script setup>
+import { ref, onMounted } from 'vue';
+import * as echarts from 'echarts';
+import LayoutCard from './LayoutCard';
+</script>
+
+<template>
+  <div></div>
+</template>
+
+<style lang="scss" scoped>
+
+</style>

+ 70 - 0
src/views/carbon/components/screen/LayoutCard.vue

@@ -0,0 +1,70 @@
+<script setup>
+
+defineProps({
+  title: {
+    type: String,
+    default: ''
+  },
+  isLarge: {
+    type: Boolean,
+    default: false
+  }
+});
+
+
+</script>
+
+<template>
+  <section :class="['layout-card', { 'layout-card_large': isLarge }]">
+    <div class="card-header">
+      <p class="title">{{ title }}</p>
+    </div>
+    <div class="card-content">
+      <slot></slot>
+    </div>
+  </section>
+</template>
+
+<style lang="scss" scoped>
+.layout-card {
+  position: relative;
+  border-radius: 10px;
+  border:1px solid rgba(49, 110,175, .3);
+  background: linear-gradient(180deg, rgba(3, 86, 189, 0.28) 0%, rgba(3, 86, 189, 0.06) 34.06%, rgba(3, 86, 189, 0.00) 50.95%, rgba(3, 86, 189, 0.28) 100%);
+
+  .card-header {
+    height: 94px;
+    background: url('@/assets/images/carbon/bg-title.png') -16px -10px no-repeat;
+    background-size: 103% 100%;
+
+    .title {
+      @include flex(x, center, start);
+      height: 46px;
+      padding-left: 57px;
+      background: linear-gradient(180deg, #FFF 28.71%, #9CD2FF 77.35%);
+      background-clip: text;
+      -webkit-background-clip: text;
+      -webkit-text-fill-color: transparent;
+      font-family: YouSheBiaoTiHei;
+      font-size: 22px;
+      font-weight: 400;
+    }
+  }
+
+  .card-content {
+    position: absolute;
+    top: 46px;
+    left: 0;
+    width: 100%;
+    height: calc(100% - 46px);
+  }
+}
+
+.layout-card_large {
+  .card-header {
+    height: 94px;
+    background: url('@/assets/images/carbon/bg-large-title1.png') 0px 0px no-repeat;
+    background-size: 100% 100%;
+  }
+}
+</style>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 381 - 0
src/views/carbon/echartOptions/index.js


+ 376 - 0
src/views/carbon/index.vue

@@ -0,0 +1,376 @@
+<script setup>
+import { ref, computed, onMounted, onUnmounted } from 'vue';
+import { useRouter } from 'vue-router';
+import { NPopselect } from 'naive-ui';
+import * as echarts from 'echarts';
+import dayjs from 'dayjs';
+import { carbonApi } from '@/api/carbon'
+import { echartLineOptions, echartGraphOptions, echart3DOptions, echartColumnarOptions } from './echartOptions';
+import VueDatePicker from '@vuepic/vue-datepicker';
+
+import SvgIcon from '@/components/SvgIcon';
+import { TheDrawerForm, TheDrawerList, BaseDatePicker, TheModal } from './components';
+
+import DataBorad from './components/screen/DataBorad.vue'
+import DataScroll from './components/screen/DataScroll.vue'
+import LayoutCard from './components/screen/LayoutCard.vue'
+import EchartEnergy from './components/screen/EchartEnergy.vue'
+import EchartColumnar from './components/screen/EchartColumnar.vue'
+
+const router = useRouter();
+
+let timerId = null;
+const tDay = dayjs();
+const currentTimer = ref(tDay.format('HH:mm:ss'));
+const currentMonth = tDay.format('YYYY.MM.DD');
+const allMonth = ref([])
+const inpVap = ref('')
+const historyDetails = ref({});
+
+const echartMonthRef = ref(null);
+const echartSewageRef = ref(null);
+const echartEnergyRef = ref(null);
+const echartMudRef = ref(null);
+
+const scrollData = ref([]);
+const scrollMapping = [
+  { label: '化石源的CO₂排放量', key: 'wsHsytkhCo2', value: '' },
+  { label: '污水处理阶段排放的CH₄的CO₂当量', key: 'wsSjclCh4Co2', value: '' },
+  { label: '污水处理阶段排放的N₂O的CO₂当量', key: 'wsTdN2oCo2', value: '' },
+  { label: '污水厂电力消耗产生的总碳排放量', key: 'nyyjDlxhZhdlCo2', value: '' },
+  { label: '进水泵房碳排', key: 'nyyjDlxhJsbfCo2', value: '' },
+  { label: '鼓风机房碳排', key: 'nyyjDlxhGfjfCo2', value: '' },
+  { label: '脱水机房碳排', key: 'nyyjDlxhTsjfCo2', value: '' },
+  { label: '消毒间碳排', key: 'nyyjDlxhXdjCo2', value: '' },
+  { label: '深度处理用电碳排', key: 'nyyjDlxhSdclCo2', value: '' },
+  { label: '污泥处置用电碳排', key: 'nyyjDlxhWnczCo2', value: '' },
+  { label: '生活区碳排', key: 'nyyjDlxhShqCo2', value: '' },
+  { label: '其他碳排', key: 'nyyjDlxhQtCo2', value: '' },
+  { label: '燃料消耗产生的碳排放量', key: 'nyyjGrrlCo2', value: '' },
+  { label: '污泥厌氧消化过程排放的CH₄的CO₂当量', key: 'wnclYyzqCo2', value: '' },
+  { label: '单独处理污泥厌氧消化产生沼液的CO₂当量', key: 'wnclDdclCo2', value: '' },
+  { label: '污泥好氧发酵过程排放的N₂O的CO₂当量', key: 'wnclHyfjN2oCo2', value: '' },
+  { label: '污泥好氧发酵过程排放的CH₄的CO₂当量', key: 'wnclWnfsCo2', value: '' },
+  { label: '污泥焚烧过程排放的CH₄的CO₂当量', key: 'wnclBwqrsCh4Co2', value: '' },
+  { label: '污泥焚烧过程排放的N₂O的CO₂当量', key: 'wnclBwqrsN2oCo2', value: '' },
+  { label: '污泥热解过程排放的CH₄的CO₂当量', key: 'wnclWnrjByhCo2', value: '' },
+  { label: '污泥热解过程排放的N₂O的CO₂当量', key: 'wnclWnrjQtN2oCo2', value: '' },
+  { label: '光伏发电替碳量', key: 'thGfCo2', value: '' },
+  { label: '回用水替代供水的替碳量', key: 'thZssCo2', value: '' },
+  { label: '污泥产物土地利用的替碳量', key: 'thWnClhCo2', value: '' },
+];
+
+const showPopover = ref(false);
+
+const isVisibleDrawerForm = ref(false);
+const isVisibleDrawerList = ref(false);
+
+const allowedMonth = computed(() => {
+  return allMonth.value.map(m => dayjs(m, 'YYYY-MM'));
+})
+
+const selectOptions = computed(() => allMonth.value.map(item => ({ label: item, value: item })));
+
+const handleType = (type) => {
+
+  if (type === 'down') {
+
+  }
+
+  if (type === 'info') {
+
+  }
+
+  if (type === 'list') {
+    isVisibleDrawerList.value = true;
+  }
+
+  if (type === 'add') {
+    isVisibleDrawerForm.value = true;
+  }
+}
+
+const handleBackPage = () => router.back();
+
+const getCurrentTimer = () => dayjs().format('HH:mm:ss');
+
+const dateDisabled = (ts, de) => {
+
+  const m = dayjs(ts).format('YYYY-MM');
+
+  console.log(allMonth.value, m, allMonth.value.includes(m));
+  return m != '2024-06'
+}
+
+const disabledDate = (date) => !allMonth.value.includes(dayjs(date).format('YYYY-MM'));
+const initAllMonth = async () => {
+  const { data: month } = await carbonApi.getAllMonth();
+  allMonth.value = month.reverse();
+  return month;
+}
+
+const initEchart = (data) => {
+  const { 
+    recent7Datas, extraMap, wsTdN2oCo2, wsSjclCh4Co2, wjtykuCo2, wsHsytkhCo2,
+    wnclYyzqCo2,
+    wnclDdclCo2,
+    wnclHyfjCh4Co2, wnclHyfjN2oCo2,
+    wnclWnfsCo2,
+    wnclBwqrsCh4Co2, wnclBwqrsN2oCo2,
+    wnclWnrjQtCh4Co2, wnclWnrjQtN2oCo2
+  } = data;
+
+  const chartMonth = echarts.init(echartMonthRef.value, 'light');
+  const echartSewage = echarts.init(echartSewageRef.value, 'light');
+  const echartEnergy = echarts.init(echartEnergyRef.value, 'light');
+  const echartMdu = echarts.init(echartMudRef.value, 'light');
+
+  // 近7月碳排放趋势
+  chartMonth.setOption(echartLineOptions(recent7Datas));
+
+  // 污水处理生化反应
+  echartSewage.setOption(echartGraphOptions([wsTdN2oCo2, wsSjclCh4Co2, wjtykuCo2, wsHsytkhCo2]));
+
+  // 能源、药剂
+  echartEnergy.setOption(echart3DOptions());
+
+  // 污泥处理-生化反应
+  echartMdu.setOption(echartColumnarOptions([
+    wnclYyzqCo2,
+    wnclDdclCo2,
+    wnclHyfjCh4Co2 + wnclHyfjN2oCo2,
+    wnclWnfsCo2,
+    wnclBwqrsCh4Co2 + wnclBwqrsN2oCo2,
+    wnclWnrjQtCh4Co2 + wnclWnrjQtN2oCo2
+  ]));
+
+  const scrollList = Object.entries(extraMap).map(([k, v], i) => {
+    const item = {};
+    return v.map((child, index) => {
+      return {
+        label: child.dictLabel,
+        key: index + i,
+        value: child.val
+      }
+    })
+  }).flat(Infinity);
+
+  // 滚动区域
+  scrollData.value = [...scrollList, ...scrollMapping].map(item => {
+    const temp = { ...item };
+    Object.entries(data).forEach(([k, v]) => {
+      if ( temp.key === k ) {
+        temp.value = v;
+      }
+    })
+    return temp;
+  }).filter(({ value }) => value);
+
+}
+
+onMounted(async () => {
+  const months = await initAllMonth();
+  const lastMonth = months[months.length - 1];
+  const { data } = await carbonApi.getDetails(lastMonth);
+
+  inpVap.value = lastMonth;
+  historyDetails.value = data;
+
+  initEchart(data);
+
+  timerId = setInterval(() => currentTimer.value = getCurrentTimer(), 1000)
+})
+
+onUnmounted(() => {
+  clearInterval(timerId);
+})
+
+</script>
+
+<template>
+  <div class="screen-viewprot">
+    <header class="header">
+      <div class="flex items-center">
+        <NPopselect :options="selectOptions" v-model:value="inpVap" scrollable>
+          <div class="calendar space-x-[4px]">
+            <span class="calendar-text">{{ inpVap }}</span>
+          </div>
+        </NPopselect>
+        <div class="timer-inner">
+          <p class="time">{{ currentTimer }}</p>
+          <p class="day text-[13px]">{{ currentMonth }}</p>
+        </div>
+        <button class="back-btn_group" @click="handleBackPage">
+          <SvgIcon name="carbon-icon-back" size="36"></SvgIcon>
+          <span class="btn">返回</span>
+        </button>
+      </div>
+    </header>
+    <main class="main">
+
+      <LayoutCard title="近7月碳排放趋势">
+        <div ref="echartMonthRef" class="w-full h-full"></div>
+      </LayoutCard>
+
+      <DataBorad :data="historyDetails"></DataBorad>
+
+      <LayoutCard title="污水处理生化反应">
+        <div ref="echartSewageRef" class="w-full h-full"></div>
+      </LayoutCard>
+
+      <LayoutCard title="能源、药剂">
+        <div class="energy-inner">
+          <div ref="echartEnergyRef" class="w-full h-full"></div>
+        </div>
+      </LayoutCard>
+
+      <DataScroll :data="scrollData"></DataScroll>
+
+      <LayoutCard title="污泥处理-生化反应">
+        <div ref="echartMudRef" class="w-full h-full"></div>
+      </LayoutCard>
+
+      <!-- <EchartColumnar></EchartColumnar> -->
+    </main>
+    <ul class="footer">
+      <li><img src="@/assets/images/carbon/bg-btn-1.png" alt="下载报告" class="img" @click="handleType('down')"></li>
+      <li><img src="@/assets/images/carbon/bg-btn-2.png" alt="申报信息" class="img" @click="handleType('info')"></li>
+      <li><img src="@/assets/images/carbon/bg-btn-3.png" alt="核算历史" class="img" @click="handleType('list')"></li>
+      <li><img src="@/assets/images/carbon/bg-btn-4.png" alt="新增核算" class="img" @click="handleType('add')"></li>
+    </ul>
+  </div>
+
+  <TheDrawerForm v-model="isVisibleDrawerForm" />
+  <TheDrawerList v-model="isVisibleDrawerList" :data="historyDetails" />
+  <!-- <TheModal /> -->
+</template>
+
+<style lang="scss" scoped>
+$bg-path: '@/assets/images/carbon/';
+$text-color_primary: #C2D8EF;
+
+.screen-viewprot {
+  display: grid;
+  grid-template-columns: repeat(1, 1fr);
+  grid-template-rows: 100px 1fr 100px;
+  width: 100vw;
+  height: 100vh;
+  background: url("@/assets/images/carbon/bg.png") 50% / cover no-repeat;
+}
+
+.header {
+  @include flex(x, start, end);
+  padding: 0 18px;
+  background: url("@/assets/images/carbon/bg-header.png") left top no-repeat;
+  background-size: cover;
+
+  .calendar {
+    width: 86px;
+    height: 22px;
+    padding-left: 8px;
+    margin-right: 54px;
+    background: url("@/assets/images/carbon/bg-calendar.png") no-repeat,
+      url("@/assets/images/carbon/bg-calendar-direction.png") 62px center no-repeat;
+    background-size: 100% 100%, 10px 10px;
+    font-size: 12px;
+    color: #fff;
+    text-shadow: 0px 1px 0px rgba(0, 22, 35, 0.75);
+    line-height: 22px;
+    font-family: D-DIN-PRO-700-Bold;
+    cursor: pointer;
+
+    span {
+      box-shadow: 0px 1px 0px 0px #001623BF;
+    }
+  }
+
+  .timer-inner {
+    padding: 16px 8px;
+    margin-right: 40px;
+    font-family: 'D-DIN-PRO-700-Bold';
+    font-weight: bold;
+    color: $text-color_primary;
+    text-align: right;
+
+    .time {
+      width: 80px;
+      font-size: 24px;
+      line-height: 24px;
+      box-shadow: 0px 1px 3px 0px #050C198A;
+    }
+  }
+
+  .back-btn_group {
+    @include flex(x, center, center);
+    font-size: 14px;
+    line-height: 18px;
+    color: $text-color_primary;
+  }
+}
+
+.main {
+  display: grid;
+  grid-gap: 26px 26px;
+  padding: 30px 48px 0 48px;
+  grid-template-columns: minmax(490px, 28%) 1fr minmax(490px, 28%);
+  grid-template-rows: minmax(300px, 50%) minmax(300px, 50%);
+  color: #fff;
+
+  .energy-inner {
+    width: 100%;
+    height: 100%;
+    font-family: 'D-DIN-PRO-700-Bold';
+    // background: url('@/assets/images/carbon/bg-3d.png') 20% 90% no-repeat;
+  }
+}
+
+.footer {
+  @include flex(x, center, center);
+  background: url("@/assets/images/carbon/Group 1321315504 (1).png") center center no-repeat;
+  background-size: cover;
+
+  li {
+    width: 180px;
+    cursor: pointer;
+
+    .img {
+      width: 100%;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.calendar {
+  .el-input__wrapper {
+    padding: 0;
+    padding-left: 16px;
+    background: transparent;
+    box-shadow: none;
+
+    .el-input__prefix,
+    .el-input__suffix {
+      display: none;
+    }
+
+    .el-input__inner {
+      font-family: 'D-DIN-PRO-700-Bold';
+      font-size: 12px;
+      color: #fff;
+      cursor: pointer;
+    }
+
+    &:hover {
+      box-shadow: none;
+    }
+  }
+
+  .el-input__wrapper.is-focus {
+    box-shadow: none;
+  }
+}
+
+.el-month-table td.current:not(.disabled) .el-date-table-cell__text {
+  background: #3153f5;
+}
+</style>

+ 12 - 0
src/views/carbon/tools/resetTheme.js

@@ -0,0 +1,12 @@
+export const inputHasBorderThemeOverrides = {
+  peers: {
+    Input: {
+      border: "1px solid #d7d9e5",
+      borderRadius: "8px",
+      borderHover: "1px solid #2454FF",
+      borderFocus: "1px solid #2454FF",
+      boxShadowFocus: "0 0 0 2px rgba(36, 84, 255, 0.2)",
+      text: "#333",
+    },
+  },
+};

+ 1 - 0
src/views/control/components/BaseInput.vue

@@ -137,6 +137,7 @@ const handleInpValue = (event, type) => {
     line-height: 28px;
     font-size: 12px;
     font-weight: bold;
+    color: #333;
   }
 
   .inp-flot_group {

+ 24 - 1
src/views/env/index.vue

@@ -1,6 +1,14 @@
 <script setup>
-import { ref } from 'vue';
+import { ref, onMounted } from 'vue';
 import { NInput, NButton } from 'naive-ui';
+import { envApi } from '@/api/env';
+
+const warnList = ref([
+ { path: '/test/waterWarning', label: '手动处理水质报警' },
+ { path: '/test/shWarning', label: '手动处理生化报警' },
+ { path: '/test/robotWarning', label: '手动处理化验室报警' },
+ { path: '/test/forecastWarning', label: '手动处理预测报警' },
+])
 
 const inpVal = ref('');
 
@@ -13,6 +21,15 @@ const handleClearEnv = () => {
   localStorage.removeItem("ENV");
   alert("remove~")
 }
+
+const handleWarnList = async (path) => {
+  await envApi.handleWarnInfo(path);
+  alert("以点击~")
+}
+
+onMounted(() => {
+  inpVal.value = localStorage.getItem("ENV")
+})
 </script>
 
 <template>
@@ -26,6 +43,12 @@ const handleClearEnv = () => {
         <NButton @click="handleClearEnv">清除</NButton>
       </li>
     </ul>
+
+    <ul class="space-y-[20px]">
+      <li v-for="item, index in warnList" :key="index" @click="handleWarnList(item.path)">
+        <NButton type="primary">{{ item.label }}</NButton>
+      </li>
+    </ul>
   </div>
 </template>
 

+ 4 - 0
src/views/screen/ScreenView.vue

@@ -68,6 +68,9 @@ const init = () => {
 init()
 
 onMounted(() => {
+
+  document.documentElement.style.fontSize = (document.documentElement.clientWidth * 10) / 1920 + 'px';
+
   //每5s刷新数据
   timer = setInterval(() => {
     init()
@@ -75,6 +78,7 @@ onMounted(() => {
 })
 
 onBeforeUnmount(() => {
+  document.documentElement.style.fontSize = '';
   clearInterval(timer)
   clearInterval(timeHour)
   timer = null;

+ 9 - 0
vite.config.ts

@@ -6,6 +6,9 @@ import vue from '@vitejs/plugin-vue'
 import vueJsx from '@vitejs/plugin-vue-jsx'
 import VueDevTools from 'vite-plugin-vue-devtools'
 import path from 'path'
+import AutoImport from 'unplugin-auto-import/vite'
+import Components from 'unplugin-vue-components/vite'
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 
 // https://vitejs.dev/config/
 export default defineConfig({
@@ -24,6 +27,12 @@ export default defineConfig({
 
       replaceStrokeWithCurrentColor: false
     }),
+    AutoImport({
+      resolvers: [ElementPlusResolver()],
+    }),
+    Components({
+      resolvers: [ElementPlusResolver()],
+    })
   ],
   resolve: {
     alias: {

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác