電價表功能
This commit is contained in:
		
							parent
							
								
									cd0bfafa35
								
							
						
					
					
						commit
						ca522b8b94
					
				
							
								
								
									
										1
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							@ -22,7 +22,6 @@ declare module 'vue' {
 | 
				
			|||||||
    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
 | 
					    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
 | 
				
			||||||
    ElRow: typeof import('element-plus/es')['ElRow']
 | 
					    ElRow: typeof import('element-plus/es')['ElRow']
 | 
				
			||||||
    ElStatistic: typeof import('element-plus/es')['ElStatistic']
 | 
					    ElStatistic: typeof import('element-plus/es')['ElStatistic']
 | 
				
			||||||
    ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
 | 
					 | 
				
			||||||
    EnergyBar: typeof import('./src/components/EnergyBar.vue')['default']
 | 
					    EnergyBar: typeof import('./src/components/EnergyBar.vue')['default']
 | 
				
			||||||
    EnergyLine: typeof import('./src/components/EnergyLine.vue')['default']
 | 
					    EnergyLine: typeof import('./src/components/EnergyLine.vue')['default']
 | 
				
			||||||
    EnergyPie: typeof import('./src/components/EnergyPie.vue')['default']
 | 
					    EnergyPie: typeof import('./src/components/EnergyPie.vue')['default']
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										213
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										213
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -8,6 +8,7 @@
 | 
				
			|||||||
      "name": "ems_front",
 | 
					      "name": "ems_front",
 | 
				
			||||||
      "version": "0.0.0",
 | 
					      "version": "0.0.0",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "axios": "^1.9.0",
 | 
				
			||||||
        "dayjs": "^1.11.13",
 | 
					        "dayjs": "^1.11.13",
 | 
				
			||||||
        "echarts": "^5.6.0",
 | 
					        "echarts": "^5.6.0",
 | 
				
			||||||
        "element-plus": "^2.9.6",
 | 
					        "element-plus": "^2.9.6",
 | 
				
			||||||
@ -1318,6 +1319,30 @@
 | 
				
			|||||||
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
 | 
					      "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/axios": {
 | 
				
			||||||
 | 
					      "version": "1.9.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "follow-redirects": "^1.15.6",
 | 
				
			||||||
 | 
					        "form-data": "^4.0.0",
 | 
				
			||||||
 | 
					        "proxy-from-env": "^1.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/axios/node_modules/form-data": {
 | 
				
			||||||
 | 
					      "version": "4.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "asynckit": "^0.4.0",
 | 
				
			||||||
 | 
					        "combined-stream": "^1.0.8",
 | 
				
			||||||
 | 
					        "es-set-tostringtag": "^2.1.0",
 | 
				
			||||||
 | 
					        "mime-types": "^2.1.12"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/balanced-match": {
 | 
					    "node_modules/balanced-match": {
 | 
				
			||||||
      "version": "1.0.2",
 | 
					      "version": "1.0.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
 | 
				
			||||||
@ -1391,6 +1416,18 @@
 | 
				
			|||||||
      "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==",
 | 
					      "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/call-bind-apply-helpers": {
 | 
				
			||||||
 | 
					      "version": "1.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "es-errors": "^1.3.0",
 | 
				
			||||||
 | 
					        "function-bind": "^1.1.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/canvg": {
 | 
					    "node_modules/canvg": {
 | 
				
			||||||
      "version": "1.5.3",
 | 
					      "version": "1.5.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/canvg/-/canvg-1.5.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/canvg/-/canvg-1.5.3.tgz",
 | 
				
			||||||
@ -1561,6 +1598,19 @@
 | 
				
			|||||||
        "node": ">=0.4.0"
 | 
					        "node": ">=0.4.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/dunder-proto": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "call-bind-apply-helpers": "^1.0.1",
 | 
				
			||||||
 | 
					        "es-errors": "^1.3.0",
 | 
				
			||||||
 | 
					        "gopd": "^1.2.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/ecc-jsbn": {
 | 
					    "node_modules/ecc-jsbn": {
 | 
				
			||||||
      "version": "0.1.2",
 | 
					      "version": "0.1.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
 | 
				
			||||||
@ -1618,6 +1668,47 @@
 | 
				
			|||||||
        "url": "https://github.com/fb55/entities?sponsor=1"
 | 
					        "url": "https://github.com/fb55/entities?sponsor=1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/es-define-property": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/es-errors": {
 | 
				
			||||||
 | 
					      "version": "1.3.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/es-object-atoms": {
 | 
				
			||||||
 | 
					      "version": "1.1.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "es-errors": "^1.3.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/es-set-tostringtag": {
 | 
				
			||||||
 | 
					      "version": "2.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "es-errors": "^1.3.0",
 | 
				
			||||||
 | 
					        "get-intrinsic": "^1.2.6",
 | 
				
			||||||
 | 
					        "has-tostringtag": "^1.0.2",
 | 
				
			||||||
 | 
					        "hasown": "^2.0.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/es6-promise": {
 | 
					    "node_modules/es6-promise": {
 | 
				
			||||||
      "version": "4.2.8",
 | 
					      "version": "4.2.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
 | 
				
			||||||
@ -1806,6 +1897,25 @@
 | 
				
			|||||||
        "node": ">=8"
 | 
					        "node": ">=8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/follow-redirects": {
 | 
				
			||||||
 | 
					      "version": "1.15.9",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
 | 
				
			||||||
 | 
					      "funding": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "individual",
 | 
				
			||||||
 | 
					          "url": "https://github.com/sponsors/RubenVerborgh"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=4.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependenciesMeta": {
 | 
				
			||||||
 | 
					        "debug": {
 | 
				
			||||||
 | 
					          "optional": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/forever-agent": {
 | 
					    "node_modules/forever-agent": {
 | 
				
			||||||
      "version": "0.6.1",
 | 
					      "version": "0.6.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 | 
				
			||||||
@ -1842,6 +1952,49 @@
 | 
				
			|||||||
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
 | 
					        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/function-bind": {
 | 
				
			||||||
 | 
					      "version": "1.1.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/ljharb"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/get-intrinsic": {
 | 
				
			||||||
 | 
					      "version": "1.3.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "call-bind-apply-helpers": "^1.0.2",
 | 
				
			||||||
 | 
					        "es-define-property": "^1.0.1",
 | 
				
			||||||
 | 
					        "es-errors": "^1.3.0",
 | 
				
			||||||
 | 
					        "es-object-atoms": "^1.1.1",
 | 
				
			||||||
 | 
					        "function-bind": "^1.1.2",
 | 
				
			||||||
 | 
					        "get-proto": "^1.0.1",
 | 
				
			||||||
 | 
					        "gopd": "^1.2.0",
 | 
				
			||||||
 | 
					        "has-symbols": "^1.1.0",
 | 
				
			||||||
 | 
					        "hasown": "^2.0.2",
 | 
				
			||||||
 | 
					        "math-intrinsics": "^1.1.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/ljharb"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/get-proto": {
 | 
				
			||||||
 | 
					      "version": "1.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "dunder-proto": "^1.0.1",
 | 
				
			||||||
 | 
					        "es-object-atoms": "^1.0.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/getpass": {
 | 
					    "node_modules/getpass": {
 | 
				
			||||||
      "version": "0.1.7",
 | 
					      "version": "0.1.7",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 | 
				
			||||||
@ -1863,6 +2016,17 @@
 | 
				
			|||||||
        "node": ">= 6"
 | 
					        "node": ">= 6"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/gopd": {
 | 
				
			||||||
 | 
					      "version": "1.2.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/ljharb"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/har-schema": {
 | 
					    "node_modules/har-schema": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
				
			||||||
@ -1893,6 +2057,42 @@
 | 
				
			|||||||
        "node": ">=8"
 | 
					        "node": ">=8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/has-symbols": {
 | 
				
			||||||
 | 
					      "version": "1.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/ljharb"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/has-tostringtag": {
 | 
				
			||||||
 | 
					      "version": "1.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "has-symbols": "^1.0.3"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/ljharb"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/hasown": {
 | 
				
			||||||
 | 
					      "version": "2.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "function-bind": "^1.1.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/he": {
 | 
					    "node_modules/he": {
 | 
				
			||||||
      "version": "1.2.0",
 | 
					      "version": "1.2.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
 | 
				
			||||||
@ -2178,6 +2378,14 @@
 | 
				
			|||||||
        "@jridgewell/sourcemap-codec": "^1.5.0"
 | 
					        "@jridgewell/sourcemap-codec": "^1.5.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/math-intrinsics": {
 | 
				
			||||||
 | 
					      "version": "1.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/memoize-one": {
 | 
					    "node_modules/memoize-one": {
 | 
				
			||||||
      "version": "6.0.0",
 | 
					      "version": "6.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
 | 
				
			||||||
@ -2462,6 +2670,11 @@
 | 
				
			|||||||
        "node": ">= 0.8.0"
 | 
					        "node": ">= 0.8.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/proxy-from-env": {
 | 
				
			||||||
 | 
					      "version": "1.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/psl": {
 | 
					    "node_modules/psl": {
 | 
				
			||||||
      "version": "1.15.0",
 | 
					      "version": "1.15.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
    "preview": "vite preview"
 | 
					    "preview": "vite preview"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "axios": "^1.9.0",
 | 
				
			||||||
    "dayjs": "^1.11.13",
 | 
					    "dayjs": "^1.11.13",
 | 
				
			||||||
    "echarts": "^5.6.0",
 | 
					    "echarts": "^5.6.0",
 | 
				
			||||||
    "element-plus": "^2.9.6",
 | 
					    "element-plus": "^2.9.6",
 | 
				
			||||||
 | 
				
			|||||||
@ -170,8 +170,6 @@ watch(
 | 
				
			|||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
  // 等待數據加載
 | 
					  // 等待數據加載
 | 
				
			||||||
  await storeDemand.getElecDemandFromBaja();
 | 
					  await storeDemand.getElecDemandFromBaja();
 | 
				
			||||||
  // 測試
 | 
					 | 
				
			||||||
  await storeDemand.getElecDatatTestBaja();
 | 
					 | 
				
			||||||
  // 初始化圖表
 | 
					  // 初始化圖表
 | 
				
			||||||
  chartInstance = echarts.init(demand_chart.value);
 | 
					  chartInstance = echarts.init(demand_chart.value);
 | 
				
			||||||
  chartInstance.setOption(chartOption.value);
 | 
					  chartInstance.setOption(chartOption.value);
 | 
				
			||||||
 | 
				
			|||||||
@ -6,11 +6,7 @@
 | 
				
			|||||||
    @select="handleSelect"
 | 
					    @select="handleSelect"
 | 
				
			||||||
  >
 | 
					  >
 | 
				
			||||||
    <el-menu-item index="chart">能源圖表</el-menu-item>
 | 
					    <el-menu-item index="chart">能源圖表</el-menu-item>
 | 
				
			||||||
    <el-sub-menu index="elecPricing">
 | 
					    <el-menu-item index="elecPricing">電價表</el-menu-item>
 | 
				
			||||||
      <template #title>電價表</template>
 | 
					 | 
				
			||||||
      <el-menu-item index="elecPricingSimple">住宅型</el-menu-item>
 | 
					 | 
				
			||||||
      <el-menu-item index="elecPricingStandard">標準型</el-menu-item>
 | 
					 | 
				
			||||||
    </el-sub-menu>
 | 
					 | 
				
			||||||
    <el-menu-item index="monthlyReport">能源報表</el-menu-item>
 | 
					    <el-menu-item index="monthlyReport">能源報表</el-menu-item>
 | 
				
			||||||
  </el-menu>
 | 
					  </el-menu>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
@ -29,13 +25,9 @@ const handleSelect = (key: string, keyPath: string[]) => {
 | 
				
			|||||||
      router.push({ name: "EnergyChart" });
 | 
					      router.push({ name: "EnergyChart" });
 | 
				
			||||||
      activeIndex.value = "chart";
 | 
					      activeIndex.value = "chart";
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case "elecPricingSimple":
 | 
					    case "elecPricing":
 | 
				
			||||||
      router.push({ name: "ElecPricingSimple" });
 | 
					      router.push({ name: "elecPricing" });
 | 
				
			||||||
      activeIndex.value = "elecPricingSimple";
 | 
					      activeIndex.value = "elecPricing";
 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case "elecPricingStandard":
 | 
					 | 
				
			||||||
      router.push({ name: "ElecPricingStandard" });
 | 
					 | 
				
			||||||
      activeIndex.value = "elecPricingStandard";
 | 
					 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case "monthlyReport":
 | 
					    case "monthlyReport":
 | 
				
			||||||
      router.push({ name: "monthlyReport" });
 | 
					      router.push({ name: "monthlyReport" });
 | 
				
			||||||
 | 
				
			|||||||
@ -13,14 +13,9 @@ const routes: Array<RouteRecordRaw> = [
 | 
				
			|||||||
        component: () => import("../views/EnergyChart.vue"),
 | 
					        component: () => import("../views/EnergyChart.vue"),
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        path: "elecPricingSimple",
 | 
					        path: "elecPricing",
 | 
				
			||||||
        name: "ElecPricingSimple",
 | 
					        name: "elecPricing",
 | 
				
			||||||
        component: () => import("../views/ElecPriceRes.vue"),
 | 
					        component: () => import("../views/EnergyPricing.vue"),
 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        path: "elecPricingStandard",
 | 
					 | 
				
			||||||
        name: "ElecPricingStandard",
 | 
					 | 
				
			||||||
        component: () => import("../views/ElecPriceStd.vue"),
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        path: "monthlyReport",
 | 
					        path: "monthlyReport",
 | 
				
			||||||
 | 
				
			|||||||
@ -14,20 +14,16 @@ const useElecDemandStore = defineStore("elecDemand", () => {
 | 
				
			|||||||
      window.requirejs(["baja!"], (baja: any) => {
 | 
					      window.requirejs(["baja!"], (baja: any) => {
 | 
				
			||||||
        let eleclist: NiagaraElecDemandData[] = [];
 | 
					        let eleclist: NiagaraElecDemandData[] = [];
 | 
				
			||||||
        baja.Ord.make(
 | 
					        baja.Ord.make(
 | 
				
			||||||
          `local:|foxs:4912|station:|neql:EMS:kw|bql:select slotPath,parent.displayName,name`
 | 
					          `local:|foxs:4918|station:|neql:EMS:kw|bql:select slotPath,parent.displayName,name,out`
 | 
				
			||||||
        ).get({
 | 
					        ).get({
 | 
				
			||||||
          cursor: {
 | 
					          cursor: {
 | 
				
			||||||
            before: () => {},
 | 
					            before: () => {},
 | 
				
			||||||
            each: (record: any) => {
 | 
					            each: (record: any) => {
 | 
				
			||||||
              const slotPath = record.get("slotPath");
 | 
					 | 
				
			||||||
              const displayName = record.get("parent$2edisplayName");
 | 
					 | 
				
			||||||
              const name = record.get("name");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              const newItem: NiagaraElecDemandData = {
 | 
					              const newItem: NiagaraElecDemandData = {
 | 
				
			||||||
                slotPath: slotPath,
 | 
					                slotPath: record.get("slotPath"),
 | 
				
			||||||
                displayName: displayName,
 | 
					                displayName: record.get("parent$2edisplayName"),
 | 
				
			||||||
                name: name,
 | 
					                name: record.get("name"),
 | 
				
			||||||
                out: 0,
 | 
					                out: record.get("out")?.get("value") ?? 0,
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              eleclist.push(newItem);
 | 
					              eleclist.push(newItem);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
@ -45,7 +41,7 @@ const useElecDemandStore = defineStore("elecDemand", () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const subscribeToHistory = (item: NiagaraElecDemandData, index: number) => {
 | 
					  const subscribeToHistory = (item: NiagaraElecDemandData, index: number) => {
 | 
				
			||||||
    const slotPath = item.slotPath;
 | 
					    const slotPath = item.slotPath;
 | 
				
			||||||
    const ordString = `local:|foxs:4912|station:|${slotPath}`;
 | 
					    const ordString = `local:|foxs:4918|station:|${slotPath}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // @ts-ignore
 | 
					    // @ts-ignore
 | 
				
			||||||
    window.require &&
 | 
					    window.require &&
 | 
				
			||||||
@ -67,12 +63,7 @@ const useElecDemandStore = defineStore("elecDemand", () => {
 | 
				
			|||||||
              );
 | 
					              );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (updatedIndex !== -1) {
 | 
					              if (updatedIndex !== -1) {
 | 
				
			||||||
                const newElecData = [...elecData.value];
 | 
					                elecData.value[updatedIndex].out = Number(newValue);
 | 
				
			||||||
                newElecData[updatedIndex] = {
 | 
					 | 
				
			||||||
                  ...newElecData[updatedIndex],
 | 
					 | 
				
			||||||
                  out: Number(newValue),
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                elecData.value = newElecData;
 | 
					 | 
				
			||||||
                console.log(`Niagara 用電需求 ${item.name} 更新:`, newValue);
 | 
					                console.log(`Niagara 用電需求 ${item.name} 更新:`, newValue);
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -106,34 +97,10 @@ const useElecDemandStore = defineStore("elecDemand", () => {
 | 
				
			|||||||
    console.log("所有訂閱已清除");
 | 
					    console.log("所有訂閱已清除");
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // 測試
 | 
					 | 
				
			||||||
  const getElecDatatTestBaja = () => {
 | 
					 | 
				
			||||||
    // @ts-ignore
 | 
					 | 
				
			||||||
    window.require &&
 | 
					 | 
				
			||||||
      // @ts-ignore
 | 
					 | 
				
			||||||
      window.requirejs(["baja!"], (baja: any) => {
 | 
					 | 
				
			||||||
        console.log("進入 bajaSubscriber 準備執行 BQL 訂閱");
 | 
					 | 
				
			||||||
        baja.Ord.make(
 | 
					 | 
				
			||||||
          `local:|foxs:4918|history:/testStation_MJM/MGCB_KWH?period=timerange;start=2025-04-20T00:00:00.000+08:00;end=2025-04-21T00:00:00.000+08:00|bql:history:HistoryRollup.rollup(baja:RelTime '3600000')`
 | 
					 | 
				
			||||||
        ).get({
 | 
					 | 
				
			||||||
          cursor: {
 | 
					 | 
				
			||||||
            before: () => {},
 | 
					 | 
				
			||||||
            each: (record: any) => {
 | 
					 | 
				
			||||||
              console.log("recordtest", record);
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            after: () => {},
 | 
					 | 
				
			||||||
            limit: -1,
 | 
					 | 
				
			||||||
            offset: 0,
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    getElecDemandFromBaja,
 | 
					    getElecDemandFromBaja,
 | 
				
			||||||
    elecData,
 | 
					    elecData,
 | 
				
			||||||
    clearAllSubscriber,
 | 
					    clearAllSubscriber
 | 
				
			||||||
    getElecDatatTestBaja,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										120
									
								
								src/stores/useElecPriceStore.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/stores/useElecPriceStore.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
				
			|||||||
 | 
					import { ref } from "vue";
 | 
				
			||||||
 | 
					import { defineStore } from "pinia";
 | 
				
			||||||
 | 
					import type { NiagaraElecData } from "../utils/types";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useElecPriceStore = defineStore("elecPriceData", () => {
 | 
				
			||||||
 | 
					  const elecData = ref<NiagaraElecData[]>([]);
 | 
				
			||||||
 | 
					  const subscribers = ref<any[]>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // get data from baja
 | 
				
			||||||
 | 
					  const getElecDataFromBaja = () => {
 | 
				
			||||||
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    window.require &&
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      window.requirejs(["baja!"], (baja: any) => {
 | 
				
			||||||
 | 
					        console.log("進入 bajaSubscriber 準備執行 BQL 訂閱");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 定義BQL 查詢
 | 
				
			||||||
 | 
					        const Total_kwhBql = `local:|foxs:4918|station:|neql:EMS:parameter|bql:select slotPath,parent.displayName,displayName,NumericInterval.historyConfig.id,out`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 執行查詢
 | 
				
			||||||
 | 
					        fetchElecData(baja, Total_kwhBql);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const fetchElecData = (baja: any, bql: string) => {
 | 
				
			||||||
 | 
					    let eleclist: NiagaraElecData[] = [];
 | 
				
			||||||
 | 
					    baja.Ord.make(bql).get({
 | 
				
			||||||
 | 
					      cursor: {
 | 
				
			||||||
 | 
					        before: () => {},
 | 
				
			||||||
 | 
					        each: (record: any) => {
 | 
				
			||||||
 | 
					          eleclist.push({
 | 
				
			||||||
 | 
					            slotPath: record.get("slotPath"),
 | 
				
			||||||
 | 
					            displayName: record.get("displayName"),
 | 
				
			||||||
 | 
					            id: record.get("NumericInterval$2ehistoryConfig$2eid").$cEncStr,
 | 
				
			||||||
 | 
					            out: record.get("out")?.get("value") ?? 0,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        after: () => {
 | 
				
			||||||
 | 
					          elecData.value = [];
 | 
				
			||||||
 | 
					          elecData.value.push(...eleclist);
 | 
				
			||||||
 | 
					          elecData.value.forEach((item, index) => {
 | 
				
			||||||
 | 
					            subscribeToCost(item, index);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        limit: -1,
 | 
				
			||||||
 | 
					        offset: 0,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const subscribeToCost = (item: NiagaraElecData, index: number) => {
 | 
				
			||||||
 | 
					    const slotPath = item.slotPath;
 | 
				
			||||||
 | 
					    const ordString = `local:|foxs:4918|station:|${slotPath}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // @ts-ignore
 | 
				
			||||||
 | 
					    window.require &&
 | 
				
			||||||
 | 
					      // @ts-ignore
 | 
				
			||||||
 | 
					      window.requirejs(["baja!"], (baja: any) => {
 | 
				
			||||||
 | 
					        // 建立訂閱器
 | 
				
			||||||
 | 
					        const subscriber = new baja.Subscriber();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // 定義 changed 事件的處理函數
 | 
				
			||||||
 | 
					        subscriber.attach("changed", (prop: any) => {
 | 
				
			||||||
 | 
					          try {
 | 
				
			||||||
 | 
					            if (prop && prop.getName() === "out") {
 | 
				
			||||||
 | 
					              // 取得 out 的新值
 | 
				
			||||||
 | 
					              const match = prop.$display.match(/^(\d+(\.\d+)?)/);
 | 
				
			||||||
 | 
					              const newValue = match ? parseFloat(match[0]) : 0;
 | 
				
			||||||
 | 
					              // 更新 elecData 中對應的 out 值
 | 
				
			||||||
 | 
					              const updatedIndex = elecData.value.findIndex(
 | 
				
			||||||
 | 
					                (data) => data.slotPath === item.slotPath
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              if (updatedIndex !== -1) {
 | 
				
			||||||
 | 
					                elecData.value[updatedIndex].out = Number(newValue);
 | 
				
			||||||
 | 
					                console.log(`電價表更新 ${item.displayName} 更新:`, newValue);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } catch (error: any) {
 | 
				
			||||||
 | 
					            console.error(
 | 
				
			||||||
 | 
					              `處理 ${item.displayName || index} 電價表變化失敗: ${
 | 
				
			||||||
 | 
					                error.message
 | 
				
			||||||
 | 
					              }`,
 | 
				
			||||||
 | 
					              error
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        baja.Ord.make(ordString)
 | 
				
			||||||
 | 
					          .get({ subscriber })
 | 
				
			||||||
 | 
					          .then(() => {
 | 
				
			||||||
 | 
					            console.log(`Successfuly subscribed to ${item.displayName}`);
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .catch((err: any) => {
 | 
				
			||||||
 | 
					            console.error(
 | 
				
			||||||
 | 
					              `訂閱 ${item.displayName || index} 失敗: ${err.message}`
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            subscriber.detach("changed"); // 移除事件監聽器
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        subscribers.value.push(subscriber);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const clearAllSubscriber = () => {
 | 
				
			||||||
 | 
					    subscribers.value.forEach((subscriber) => {
 | 
				
			||||||
 | 
					      subscriber.detach("changed");
 | 
				
			||||||
 | 
					      subscriber.unsubscribeAll(); // 移除所有訂閱
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    subscribers.value = [];
 | 
				
			||||||
 | 
					    console.log("所有訂閱已清除");
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    getElecDataFromBaja,
 | 
				
			||||||
 | 
					    clearAllSubscriber,
 | 
				
			||||||
 | 
					    elecData,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default useElecPriceStore;
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/utils/CalcuEleCost.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/utils/CalcuEleCost.ts
									
									
									
									
									
										Normal file
									
								
							@ -12,3 +12,32 @@ export interface NiagaraElecDemandData {
 | 
				
			|||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
  out: number; 
 | 
					  out: number; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DailyResult {
 | 
				
			||||||
 | 
					  dateStr: string;
 | 
				
			||||||
 | 
					  off: number;
 | 
				
			||||||
 | 
					  half: number;
 | 
				
			||||||
 | 
					  peak: number;
 | 
				
			||||||
 | 
					  offcost:number;
 | 
				
			||||||
 | 
					  halfcost:number;
 | 
				
			||||||
 | 
					  peakcost:number;
 | 
				
			||||||
 | 
					  dailyEleCost: number;
 | 
				
			||||||
 | 
					  dailyFlowCost: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ElecCostSummary {
 | 
				
			||||||
 | 
					  dailyResults: DailyResult[];
 | 
				
			||||||
 | 
					  totalEleCost: number;
 | 
				
			||||||
 | 
					  totalFlowCost: number;
 | 
				
			||||||
 | 
					  total_Off: number;
 | 
				
			||||||
 | 
					  total_half: number;
 | 
				
			||||||
 | 
					  total_peak: number;
 | 
				
			||||||
 | 
					  total_OffCost: number;
 | 
				
			||||||
 | 
					  total_halfCost: number;
 | 
				
			||||||
 | 
					  total_peakCost: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DailyEntry {
 | 
				
			||||||
 | 
					  time: Date;
 | 
				
			||||||
 | 
					  value: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										543
									
								
								src/views/EnergyPricing.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										543
									
								
								src/views/EnergyPricing.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,543 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <el-row :gutter="20">
 | 
				
			||||||
 | 
					    <el-col :span="24">
 | 
				
			||||||
 | 
					      <h2>適合每月用電超過5,300度之住宅及小商店評估選用。</h2>
 | 
				
			||||||
 | 
					    </el-col>
 | 
				
			||||||
 | 
					    <el-col :span="16" :offset="4">
 | 
				
			||||||
 | 
					      <table class="">
 | 
				
			||||||
 | 
					        <thead>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <th colspan="8" class="">
 | 
				
			||||||
 | 
					              <div style="display: flex; justify-content: space-between">
 | 
				
			||||||
 | 
					                標準型時間電價三段式
 | 
				
			||||||
 | 
					                <el-button-group>
 | 
				
			||||||
 | 
					                  <el-button
 | 
				
			||||||
 | 
					                    type="warning"
 | 
				
			||||||
 | 
					                    plain
 | 
				
			||||||
 | 
					                    :icon="Edit"
 | 
				
			||||||
 | 
					                    v-if="!stand3isEditing"
 | 
				
			||||||
 | 
					                    @click.stop.prevent="startEditing()"
 | 
				
			||||||
 | 
					                    >編輯</el-button
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                  <template v-else>
 | 
				
			||||||
 | 
					                    <el-button
 | 
				
			||||||
 | 
					                      type="warning"
 | 
				
			||||||
 | 
					                      plain
 | 
				
			||||||
 | 
					                      :icon="CircleCheck"
 | 
				
			||||||
 | 
					                      @click.stop.prevent="confirmChanges()"
 | 
				
			||||||
 | 
					                      >確認</el-button
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                    <el-button
 | 
				
			||||||
 | 
					                      type="warning"
 | 
				
			||||||
 | 
					                      plain
 | 
				
			||||||
 | 
					                      :icon="CircleClose"
 | 
				
			||||||
 | 
					                      @click.stop.prevent="onCancel()"
 | 
				
			||||||
 | 
					                      >取消</el-button
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                  </template>
 | 
				
			||||||
 | 
					                </el-button-group>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </th>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </thead>
 | 
				
			||||||
 | 
					        <tbody>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="6" class="">分類</td>
 | 
				
			||||||
 | 
					            <td class="">夏月<br />(6/1~9/30)</td>
 | 
				
			||||||
 | 
					            <td class="">非夏月<br />(夏月以外的時間)</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="6" class="bg-brown">基本電費</td>
 | 
				
			||||||
 | 
					            <td colspan="2" rowspan="2" class="bg-brown">按戶計收</td>
 | 
				
			||||||
 | 
					            <td colspan="2" class="bg-brown">單相</td>
 | 
				
			||||||
 | 
					            <td rowspan="2" class="bg-brown">每戶每月</td>
 | 
				
			||||||
 | 
					            <td colspan="2" class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[0]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="2" class="bg-brown">三相</td>
 | 
				
			||||||
 | 
					            <td colspan="2" class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[1]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="4" class="bg-brown">經常契約</td>
 | 
				
			||||||
 | 
					            <td rowspan="4" class="bg-brown">每瓩每月</td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[2]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[3]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="4" class="bg-brown">非夏日契約</td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[4]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[5]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="4" class="bg-brown">週六半尖峰契約</td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[6]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[7]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td colspan="4" class="bg-brown">離峰契約</td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[8]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-brown">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[9]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="10">流動電費</td>
 | 
				
			||||||
 | 
					            <td rowspan="5">週一~週五</td>
 | 
				
			||||||
 | 
					            <td class="bg-red">尖峰時間</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightred" width="50">夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightred" width="120">16:00 ~ 22:00</td>
 | 
				
			||||||
 | 
					            <td rowspan="10">每度</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightred">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[10]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightred">-</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="2" class="bg-yellow">半尖峰時間</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">09:00 ~ 16:00<br />22:00 ~ 24:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[11]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">-</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">非夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">06:00 ~ 11:00<br />14:00 ~ 24:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">-</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[12]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="2" class="bg-green">離峰時間</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">00:00 ~ 09:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[13]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">-</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">非夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              00:00 ~ 06:00<br />
 | 
				
			||||||
 | 
					              11:00 ~ 14:00
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">-</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[14]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="4">週六</td>
 | 
				
			||||||
 | 
					            <td rowspan="2" class="bg-yellow">半尖峰時間</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">09:00 ~ 24:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[15]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">-</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">非夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">
 | 
				
			||||||
 | 
					              06:00 ~ 11:00<br />
 | 
				
			||||||
 | 
					              14:00 ~ 24:00
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">-</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightyellow">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[16]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td rowspan="2" class="bg-green">離峰時間</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">00:00 ~ 09:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[17]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">-</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">非夏月</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">00:00 ~ 06:00<br />11:00 ~ 14:00</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">-</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[18]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <td>週日及離峰日</td>
 | 
				
			||||||
 | 
					            <td class="bg-green">離峰時間</td>
 | 
				
			||||||
 | 
					            <td colspan="2" class="bg-lightgreen">全日</td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[19]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td class="bg-lightgreen">
 | 
				
			||||||
 | 
					              <el-input
 | 
				
			||||||
 | 
					                type="number"
 | 
				
			||||||
 | 
					                v-model.number="stand3Value[20]"
 | 
				
			||||||
 | 
					                style="width: 140px"
 | 
				
			||||||
 | 
					                :disabled="!stand3isEditing"
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					    </el-col>
 | 
				
			||||||
 | 
					  </el-row>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { ref, watch } from "vue";
 | 
				
			||||||
 | 
					import { Edit, CircleClose, CircleCheck } from "@element-plus/icons-vue";
 | 
				
			||||||
 | 
					import useElecPriceStore from "../stores/useElecPriceStore";
 | 
				
			||||||
 | 
					import axios from "axios";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const storeElecPrice = useElecPriceStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const stand3isEditing = ref(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const stand3Value = ref<number[]>(new Array(21).fill(null));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const beforeEditValues = ref<number[]>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const displayNameToIndex: { [key: string]: number | number[] } = {
 | 
				
			||||||
 | 
					  基本半尖峰夏月: 4,
 | 
				
			||||||
 | 
					  基本離峰夏月: 8,
 | 
				
			||||||
 | 
					  基本離峰非夏月: 9,
 | 
				
			||||||
 | 
					  基本半尖峰非夏月: 5,
 | 
				
			||||||
 | 
					  流動週日離峰夏月: 19,
 | 
				
			||||||
 | 
					  流動週日離峰非夏月: 20,
 | 
				
			||||||
 | 
					  流動週六離峰非夏月: 18,
 | 
				
			||||||
 | 
					  基本經常夏月: 2,
 | 
				
			||||||
 | 
					  基本按戶單相: 0,
 | 
				
			||||||
 | 
					  基本經常非夏月: 3,
 | 
				
			||||||
 | 
					  基本按戶三相: 1,
 | 
				
			||||||
 | 
					  流動平日半尖峰非夏月: 12,
 | 
				
			||||||
 | 
					  流動平日半尖峰夏月: 11,
 | 
				
			||||||
 | 
					  流動平日尖峰夏月: 10,
 | 
				
			||||||
 | 
					  流動週六離峰夏月: 17,
 | 
				
			||||||
 | 
					  流動週六半尖峰非夏月: 16,
 | 
				
			||||||
 | 
					  流動平日離峰夏月: 13,
 | 
				
			||||||
 | 
					  流動週六半尖峰夏月: 15,
 | 
				
			||||||
 | 
					  流動平日離峰非夏月: 14,
 | 
				
			||||||
 | 
					  基本週六半尖峰非夏月: 7,
 | 
				
			||||||
 | 
					  基本週六半尖峰夏月: 6,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const initialStand3Values = ref<number[]>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const startEditing = () => {
 | 
				
			||||||
 | 
					  beforeEditValues.value = [...stand3Value.value];
 | 
				
			||||||
 | 
					  stand3isEditing.value = true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const resetStand3Values = () => {
 | 
				
			||||||
 | 
					  if (initialStand3Values.value.length > 0) {
 | 
				
			||||||
 | 
					    stand3Value.value = [...initialStand3Values.value];
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    stand3Value.value = new Array(21).fill(null);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const updatePrice = async (slotPath: string, out: number) => {
 | 
				
			||||||
 | 
					  const domain = window.location.origin;
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    console.log("updatePrice",`${domain}/obix/config/${slotPath}/in2/value`)
 | 
				
			||||||
 | 
					    const res = await axios.put(
 | 
				
			||||||
 | 
					      `${domain}/obix/config/${slotPath}/in2/value`,
 | 
				
			||||||
 | 
					      `<real name="in" val="${out}"/> `,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        headers: { "Content-Type": "text/xml" },
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    if (res.status === 200) {
 | 
				
			||||||
 | 
					      console.log(`成功更新 ${slotPath} 為 ${out}`);
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      console.error(`更新 ${slotPath} 失敗,狀態碼: ${res.status}`);
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (error) {
 | 
				
			||||||
 | 
					    console.error(`更新 ${slotPath} 出錯:`, error);
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const confirmChanges = async () => {
 | 
				
			||||||
 | 
					  stand3isEditing.value = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const elecData = storeElecPrice.elecData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const failedUpdates: { slotPath: string; out: number }[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!elecData || elecData.length === 0) {
 | 
				
			||||||
 | 
					    console.warn("useElecPriceStore.elecData 為空,無法更新 stand3Value");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 循環遍歷所有值,找出修改過的
 | 
				
			||||||
 | 
					  for (let i = 0; i < stand3Value.value.length; i++) {
 | 
				
			||||||
 | 
					    if (stand3Value.value[i] !== beforeEditValues.value[i]) {
 | 
				
			||||||
 | 
					      // 找到對應的 displayName
 | 
				
			||||||
 | 
					      const displayName = Object.keys(displayNameToIndex).find((key) => {
 | 
				
			||||||
 | 
					        const index = displayNameToIndex[key];
 | 
				
			||||||
 | 
					        if (typeof index === "number") {
 | 
				
			||||||
 | 
					          return index === i;
 | 
				
			||||||
 | 
					        } else if (Array.isArray(index)) {
 | 
				
			||||||
 | 
					          return index.includes(i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (displayName) {
 | 
				
			||||||
 | 
					        // 查找 elecData 中對應的 item
 | 
				
			||||||
 | 
					        const item = elecData.find((item) => item.displayName === displayName);
 | 
				
			||||||
 | 
					        if (item) {
 | 
				
			||||||
 | 
					          // 移除 "slot:/" 前綴
 | 
				
			||||||
 | 
					          const slotPath = item.slotPath.startsWith("slot:/")
 | 
				
			||||||
 | 
					            ? item.slotPath.slice(6) // 移除 "slot:/"
 | 
				
			||||||
 | 
					            : item.slotPath; // 如果没有前綴,則保持不變
 | 
				
			||||||
 | 
					          // 更新 Niagara
 | 
				
			||||||
 | 
					          const success = await updatePrice(slotPath, stand3Value.value[i]);
 | 
				
			||||||
 | 
					          if (!success) {
 | 
				
			||||||
 | 
					            failedUpdates.push({
 | 
				
			||||||
 | 
					              slotPath: item.slotPath,
 | 
				
			||||||
 | 
					              out: stand3Value.value[i],
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          console.warn(`找不到 displayName 為 ${displayName} 的 elecData`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        console.warn(`找不到 index 為 ${i} 的 displayName`);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (failedUpdates.length > 0) {
 | 
				
			||||||
 | 
					    console.error("以下更新失敗:", failedUpdates);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    console.log("所有更新成功");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 更新 initialStand3Values
 | 
				
			||||||
 | 
					  initialStand3Values.value = [...stand3Value.value];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onCancel = () => {
 | 
				
			||||||
 | 
					  stand3isEditing.value = false;
 | 
				
			||||||
 | 
					  resetStand3Values();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const updateStand3Values = () => {
 | 
				
			||||||
 | 
					  const elecData = storeElecPrice.elecData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!elecData || elecData.length === 0) {
 | 
				
			||||||
 | 
					    console.warn("useElecPriceStore.elecData 為空,無法更新 stand3Value");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const tempStand3Value = new Array(21).fill(null); // 儲存新值
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  elecData.forEach((item) => {
 | 
				
			||||||
 | 
					    const index = displayNameToIndex[item.displayName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (typeof index === "number") {
 | 
				
			||||||
 | 
					      tempStand3Value[index] = item.out as number;
 | 
				
			||||||
 | 
					    } else if (Array.isArray(index)) {
 | 
				
			||||||
 | 
					      index.forEach((i) => {
 | 
				
			||||||
 | 
					        tempStand3Value[i] = item.out as number;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 更新 stand3Value
 | 
				
			||||||
 | 
					  stand3Value.value = [...tempStand3Value];
 | 
				
			||||||
 | 
					  initialStand3Values.value = [...tempStand3Value]; //緩存一份
 | 
				
			||||||
 | 
					  console.log("成功更新 stand3Value:", stand3Value.value);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  () => storeElecPrice.elecData,
 | 
				
			||||||
 | 
					  (newValue) => {
 | 
				
			||||||
 | 
					    console.log("費率:", newValue);
 | 
				
			||||||
 | 
					    updateStand3Values();
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    immediate: true,
 | 
				
			||||||
 | 
					    deep: true,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style scoped>
 | 
				
			||||||
 | 
					h2 {
 | 
				
			||||||
 | 
					  font-size: 1.2em;
 | 
				
			||||||
 | 
					  font-weight: bold;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  margin-bottom: 30px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					th,
 | 
				
			||||||
 | 
					td {
 | 
				
			||||||
 | 
					  border: 1px solid #9c9a97;
 | 
				
			||||||
 | 
					  padding: 0.5rem;
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  background: #e9e2d1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					th {
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  line-height: 2;
 | 
				
			||||||
 | 
					  background: #f3ac0a;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td {
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  line-height: 1.2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-brown {
 | 
				
			||||||
 | 
					  background: #d8cdb2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-red {
 | 
				
			||||||
 | 
					  background: #ce1c45;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-lightred {
 | 
				
			||||||
 | 
					  background: #fee5dd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-green {
 | 
				
			||||||
 | 
					  background: #4da62c;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-lightgreen {
 | 
				
			||||||
 | 
					  background: #dae9c9;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-yellow {
 | 
				
			||||||
 | 
					  background: #eeb612;
 | 
				
			||||||
 | 
					  color: #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.bg-lightyellow {
 | 
				
			||||||
 | 
					  background: #f3e5a3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -8,7 +8,19 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { onMounted, onUnmounted } from "vue";
 | 
				
			||||||
import Navbar from "../components/Navbar.vue";
 | 
					import Navbar from "../components/Navbar.vue";
 | 
				
			||||||
 | 
					import useElecPriceStore from "../stores/useElecPriceStore";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const storeElecPrice = useElecPriceStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onMounted(async () => {
 | 
				
			||||||
 | 
					  await storeElecPrice.getElecDataFromBaja();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					onUnmounted(() => {
 | 
				
			||||||
 | 
					  storeElecPrice.clearAllSubscriber();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user