設定 : 新增棟別、時間電價、MQTT解析 | 能源管理: 即時需量、碳排當量新增
This commit is contained in:
parent
80fcfda16c
commit
c8d8fbf254
453
package-lock.json
generated
453
package-lock.json
generated
@ -22,6 +22,7 @@
|
||||
"echarts": "^5.4.3",
|
||||
"flag-icons": "^7.2.3",
|
||||
"jquery-ui": "^1.14.1",
|
||||
"json-schema-generator": "^2.0.6",
|
||||
"mqtt": "^5.10.3",
|
||||
"pinia": "^2.1.7",
|
||||
"requirejs": "^2.3.6",
|
||||
@ -1152,8 +1153,6 @@
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
@ -1298,6 +1297,24 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/assign-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
|
||||
@ -1366,6 +1383,21 @@
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/aws4": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
|
||||
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
|
||||
@ -1429,6 +1461,15 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"node_modules/big.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
@ -1478,8 +1519,7 @@
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
@ -1628,6 +1668,12 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
@ -1853,6 +1899,12 @@
|
||||
"url": "https://opencollective.com/core-js"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
@ -2038,6 +2090,18 @@
|
||||
"url": "https://opencollective.com/daisyui"
|
||||
}
|
||||
},
|
||||
"node_modules/dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz",
|
||||
@ -2175,6 +2239,16 @@
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/echarts": {
|
||||
"version": "5.4.3",
|
||||
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.3.tgz",
|
||||
@ -2417,6 +2491,12 @@
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
@ -2448,12 +2528,19 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.2",
|
||||
@ -2486,9 +2573,7 @@
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"node_modules/fast-unique-numbers": {
|
||||
"version": "8.0.13",
|
||||
@ -2570,6 +2655,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
@ -2660,6 +2754,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
@ -2705,6 +2808,29 @@
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"deprecated": "this library is no longer supported",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
@ -2840,6 +2966,21 @@
|
||||
"readable-stream": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8",
|
||||
"npm": ">=1.3.7"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
@ -3016,6 +3157,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-windows": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||
@ -3043,6 +3190,12 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/jest-worker": {
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||
@ -3101,6 +3254,12 @@
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
@ -3108,12 +3267,47 @@
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/json-promise": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/json-promise/-/json-promise-1.1.8.tgz",
|
||||
"integrity": "sha512-rz31P/7VfYnjQFrF60zpPTT0egMPlc8ZvIQHWs4ZtNZNnAXRmXo6oS+6eyWr5sEMG03OVhklNrTXxiIRYzoUgQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bluebird": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
|
||||
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
|
||||
"license": "(AFL-2.1 OR BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/json-schema-generator": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-generator/-/json-schema-generator-2.0.6.tgz",
|
||||
"integrity": "sha512-WyWDTK3jnv/OBI43uWw7pTGoDQ62PfccySZCHTBsOfS6D9QhsQr+95Wcwq5lqjzkiDQkTNkWzXEqHOhswfufmw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-promise": "^1.1.8",
|
||||
"mkdirp": "^0.5.0",
|
||||
"optimist": "^0.6.1",
|
||||
"pretty-data": "^0.40.0",
|
||||
"request": "^2.81.0"
|
||||
},
|
||||
"bin": {
|
||||
"json-schema-generator": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "1.0.2",
|
||||
@ -3139,6 +3333,21 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsprim": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
|
||||
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.4.0",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
|
||||
@ -3395,6 +3604,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
|
||||
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.6"
|
||||
},
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mqtt": {
|
||||
"version": "5.10.3",
|
||||
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.10.3.tgz",
|
||||
@ -3634,6 +3855,15 @@
|
||||
"js-sdsl": "4.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@ -3754,6 +3984,22 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==",
|
||||
"license": "MIT/X11",
|
||||
"dependencies": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/optimist/node_modules/minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pascalcase": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
|
||||
@ -3784,6 +4030,12 @@
|
||||
"integrity": "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
@ -4085,6 +4337,15 @@
|
||||
"posthtml-render": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-data": {
|
||||
"version": "0.40.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-data/-/pretty-data-0.40.0.tgz",
|
||||
"integrity": "sha512-YFLnEdDEDnkt/GEhet5CYZHCvALw6+Elyb/tp8kQG03ZSIuzeaDWpZYndCXwgqu4NAjh1PI534dhDS1mHarRnQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
@ -4110,16 +4371,35 @@
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"punycode": "^2.3.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/lupomontero"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.5.3",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||
@ -4285,6 +4565,52 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.3",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/request/node_modules/form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/requirejs": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
|
||||
@ -4418,6 +4744,12 @@
|
||||
"ret": "~0.1.10"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.69.5",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz",
|
||||
@ -4787,6 +5119,31 @@
|
||||
"node": ">= 10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/sshpk": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
|
||||
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"bin": {
|
||||
"sshpk-conv": "bin/sshpk-conv",
|
||||
"sshpk-sign": "bin/sshpk-sign",
|
||||
"sshpk-verify": "bin/sshpk-verify"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
@ -5387,6 +5744,19 @@
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz",
|
||||
@ -5410,6 +5780,24 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||
@ -5620,8 +6008,6 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
@ -5647,6 +6033,16 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@ -5656,6 +6052,20 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz",
|
||||
@ -5895,6 +6305,15 @@
|
||||
"integrity": "sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/worker-timers": {
|
||||
"version": "7.1.8",
|
||||
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"echarts": "^5.4.3",
|
||||
"flag-icons": "^7.2.3",
|
||||
"jquery-ui": "^1.14.1",
|
||||
"json-schema-generator": "^2.0.6",
|
||||
"mqtt": "^5.10.3",
|
||||
"pinia": "^2.1.7",
|
||||
"requirejs": "^2.3.6",
|
||||
|
@ -1,4 +1,6 @@
|
||||
export const GET_BUILDING_API = `/api/Device/GetBuild`;
|
||||
export const GET_BUILDING_API = `/AssetManage/GetBuildingList`;
|
||||
export const POST_BUILDING_API = `/AssetManage/SaveBuilding`;
|
||||
export const DELETE_BUILDING_API = `/AssetManage/DeleteBuilding`;
|
||||
export const GET_AUTHPAGE_API = `/api/GetUsrFroList`;
|
||||
export const GET_SUBAUTHPAGE_API = `/api/Device/GetMainSub`;
|
||||
export const GET_ALL_DEVICE_API = `/api/Device/GetAllDevice`;
|
||||
|
@ -1,5 +1,7 @@
|
||||
import {
|
||||
GET_BUILDING_API,
|
||||
POST_BUILDING_API,
|
||||
DELETE_BUILDING_API,
|
||||
GET_AUTHPAGE_API,
|
||||
GET_SUBAUTHPAGE_API,
|
||||
GET_ALL_DEVICE_API,
|
||||
@ -16,6 +18,27 @@ export const getBuildings = async () => {
|
||||
});
|
||||
};
|
||||
|
||||
export const postBuildings = async ({ full_name, building_guid }) => {
|
||||
const res = await instance.post(POST_BUILDING_API, {
|
||||
full_name,
|
||||
building_guid,
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteBuildings = async (building_guid) => {
|
||||
const res = await instance.post(DELETE_BUILDING_API, { building_guid });
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getAuth = async (lang) => {
|
||||
const res = await instance.post(GET_AUTHPAGE_API, {
|
||||
lang,
|
||||
|
@ -8,3 +8,15 @@ export const GET_SEARCH_API = `/api/Energe/GetFilter`;
|
||||
export const GET_REPORT_API = `/api/Energe/GetReport`;
|
||||
export const GET_Excel_API = `/api/Energe/GetReportExcel`;
|
||||
|
||||
// 即時需量
|
||||
export const GET_DEMAND_API = `/api/Energe/SearchDemandValue`;
|
||||
export const POST_ADD_DEMAND_API = `/api/Energe/AddDemandValue`;
|
||||
export const POST_EDIT_DEMAND_API = `/api/Energe/UpdateDemandValue`;
|
||||
|
||||
// 碳排係數
|
||||
export const GET_CARBON_API = `/api/Energe/SearchCarbonValue`;
|
||||
export const POST_EDIT_CARBON_API = `/api/Energe/UpdateCarbonValue`;
|
||||
|
||||
// 時間電價
|
||||
export const GET_TIME_ELEC_API = `/api/Energe/SearchTimeElec`;
|
||||
export const POST_TIME_ELEC_API = `/api/Energe/UpdateTimeElecValue`;
|
@ -6,6 +6,12 @@ import {
|
||||
GET_SEARCH_API,
|
||||
GET_REPORT_API,
|
||||
GET_Excel_API,
|
||||
GET_DEMAND_API,
|
||||
POST_EDIT_DEMAND_API,
|
||||
GET_CARBON_API,
|
||||
POST_EDIT_CARBON_API,
|
||||
GET_TIME_ELEC_API,
|
||||
POST_TIME_ELEC_API
|
||||
} from "./api";
|
||||
import instance, { fileInstance } from "@/util/request";
|
||||
import apihandler from "@/util/apihandler";
|
||||
@ -110,3 +116,71 @@ export const getExcel = async ({
|
||||
downloadExcel
|
||||
);
|
||||
};
|
||||
|
||||
export const getDemand = async (building_guid) => {
|
||||
const res = await instance.post(GET_DEMAND_API, {building_guid});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postEditDemand = async ({ id, contract, alert, reset, building_guid }) => {
|
||||
const res = await instance.put(POST_EDIT_DEMAND_API, {
|
||||
id,
|
||||
contract,
|
||||
alert,
|
||||
reset,
|
||||
building_guid
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCarbonValue = async (building_guid) => {
|
||||
const res = await instance.post(GET_CARBON_API, {building_guid});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postEditCarbonValue = async ({ id, coefficient, building_guid }) => {
|
||||
const res = await instance.put(POST_EDIT_CARBON_API, {
|
||||
id,
|
||||
coefficient,
|
||||
building_guid
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const getTimeElec = async (building_guid) => {
|
||||
const res = await instance.post(GET_TIME_ELEC_API, {building_guid});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
||||
export const postTimeElec = async ({ sheet, cost, building_guid }) => {
|
||||
const res = await instance.put(POST_TIME_ELEC_API, {
|
||||
sheet,
|
||||
cost,
|
||||
building_guid
|
||||
});
|
||||
|
||||
return apihandler(res.code, res.data, {
|
||||
msg: res.msg,
|
||||
code: res.code,
|
||||
});
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ const curWidth = computed(() => {
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-500 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-300 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
/>
|
||||
<input
|
||||
v-else
|
||||
@ -84,7 +84,7 @@ const curWidth = computed(() => {
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:required="required"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-500 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
class="text-lg text-white bg-transparent w-full input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:bg-base-300 read-only:text-zinc-300 read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0"
|
||||
/>
|
||||
<div :class="twMerge(isBottomLabelExist ? 'label' : '')">
|
||||
<span class="label-text-alt"><slot name="bottomLeft"></slot></span>
|
||||
|
@ -6,7 +6,6 @@ import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
|
||||
const getBui = async () => {
|
||||
console.log(store.buildings);
|
||||
const res = await getBuildings();
|
||||
store.buildings = res.data;
|
||||
store.selectedBuilding = res?.data[0];
|
||||
@ -33,10 +32,10 @@ onMounted(() => {
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||
class="dropdown-content w-48 left-8 translate-y-2 z-[1] menu py-3 shadow rounded bg-[#4c625e] border text-center"
|
||||
>
|
||||
<li
|
||||
class="text-white my-1 text-base"
|
||||
class="text-white my-1 text-base cursor-pointer"
|
||||
v-for="bui in store.buildings"
|
||||
:key="bui.building_tag"
|
||||
@click="selectBuilding(bui)"
|
||||
|
@ -98,7 +98,10 @@
|
||||
"ranking": "排名",
|
||||
"subtotal": "小计",
|
||||
"unit_price": "单价",
|
||||
"total_amount": "金额总计"
|
||||
"total_amount": "金额总计",
|
||||
"elec_price_list": "电价表",
|
||||
"residential": "住宅型",
|
||||
"standard": "标准型"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "显示警告",
|
||||
@ -274,7 +277,8 @@
|
||||
"index": "编号",
|
||||
"floor_plan": "平面图",
|
||||
"department": "部门",
|
||||
"department_name": "部门名称"
|
||||
"department_name": "部门名称",
|
||||
"building": "栋别"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "帐号管理",
|
||||
|
@ -98,7 +98,10 @@
|
||||
"ranking": "排名",
|
||||
"subtotal": "小計",
|
||||
"unit_price": "單價",
|
||||
"total_amount": "金額總計"
|
||||
"total_amount": "金額總計",
|
||||
"elec_price_list": "電價表",
|
||||
"residential": "住宅型",
|
||||
"standard": "標準型"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "顯示警告",
|
||||
@ -274,7 +277,8 @@
|
||||
"index": "編號",
|
||||
"floor_plan": "平面圖",
|
||||
"department": "部門",
|
||||
"department_name": "部門名稱"
|
||||
"department_name": "部門名稱",
|
||||
"building": "棟別"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "帳號管理",
|
||||
|
@ -98,7 +98,10 @@
|
||||
"ranking": "Ranking",
|
||||
"subtotal": "Subtotal",
|
||||
"unit_price": "Unit price",
|
||||
"total_amount": "Total amount"
|
||||
"total_amount": "Total amount",
|
||||
"elec_price_list": "Electricity Price List",
|
||||
"residential": "Residential",
|
||||
"standard": "Standard"
|
||||
},
|
||||
"alarm": {
|
||||
"title": "Warning",
|
||||
@ -274,7 +277,8 @@
|
||||
"index": "Serial Number",
|
||||
"floor_plan": "Floor Plan",
|
||||
"department": "Department",
|
||||
"department_name": "Department Name"
|
||||
"department_name": "Department Name",
|
||||
"building": "Building"
|
||||
},
|
||||
"accountManagement": {
|
||||
"account_title": "Account Management",
|
||||
|
@ -59,7 +59,8 @@ import {
|
||||
faEyeSlash,
|
||||
faGlobe,
|
||||
faDownload,
|
||||
faStream
|
||||
faStream,
|
||||
faSave,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
/* add icons to the library */
|
||||
@ -120,7 +121,8 @@ library.add(
|
||||
faEyeSlash,
|
||||
faGlobe,
|
||||
faDownload,
|
||||
faStream
|
||||
faStream,
|
||||
faSave
|
||||
);
|
||||
|
||||
export default library;
|
||||
|
@ -3,9 +3,12 @@ import BarChart from "@/components/chart/BarChart.vue";
|
||||
import { ref, onMounted, inject, watch } from "vue";
|
||||
import CarbonEmissionModal from "./CarbonEmissionModal.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { getCarbonValue } from "@/apis/energy";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t, locale } = useI18n();
|
||||
const { taipower_data } = inject("energy_data");
|
||||
const editRecord = ref(null);
|
||||
const carbonData = ref(null);
|
||||
const defaultChartOption = ref({
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
@ -79,23 +82,22 @@ watch(locale, () => {
|
||||
updateChartNames();
|
||||
});
|
||||
|
||||
const openModal = (record) => {
|
||||
if (record) {
|
||||
editRecord.value = record;
|
||||
} else {
|
||||
editRecord.value = null;
|
||||
const getData = async () => {
|
||||
if (store.selectedBuilding.building_guid) {
|
||||
const res = await getCarbonValue(store.selectedBuilding.building_guid);
|
||||
carbonData.value = res.data[0];
|
||||
}
|
||||
carbon_emission_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
editRecord.value = null;
|
||||
carbon_emission_item.close();
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
console.log("ok");
|
||||
};
|
||||
watch(
|
||||
() => store.selectedBuilding,
|
||||
(newBuilding) => {
|
||||
if (newBuilding) {
|
||||
getData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
updateChartNames();
|
||||
@ -109,10 +111,8 @@ onMounted(() => {
|
||||
{{ $t("energy.monthly_carbon_emission_and_reduction") }}
|
||||
</div>
|
||||
<CarbonEmissionModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:editRecord="editRecord"
|
||||
:fetchData="fetchData"
|
||||
:carbonData="carbonData"
|
||||
:getData="getData"
|
||||
/>
|
||||
</div>
|
||||
<div class="bar-box">
|
||||
|
@ -1,35 +1,33 @@
|
||||
<script setup>
|
||||
import { inject, defineProps, watch, ref } from "vue";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import { postAlertMember } from "@/apis/alert";
|
||||
import { postEditCarbonValue } from "@/apis/energy";
|
||||
import * as yup from "yup";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
const props = defineProps({
|
||||
openModal: Function,
|
||||
onCancel: Function,
|
||||
editRecord: Object,
|
||||
fetchData: Function,
|
||||
carbonData: Object,
|
||||
getData: Function,
|
||||
});
|
||||
|
||||
let scheme = yup.object({
|
||||
factor: yup.number().required(t("button.required")),
|
||||
coefficient: yup.number().required(t("button.required")),
|
||||
});
|
||||
|
||||
const form = ref(null);
|
||||
const formState = ref({
|
||||
factor: null,
|
||||
coefficient: null,
|
||||
});
|
||||
|
||||
const SaveCheckAuth = ref([]);
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset } = useFormErrorMessage(
|
||||
scheme.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.editRecord,
|
||||
() => props.carbonData,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
formState.value = {
|
||||
@ -42,21 +40,29 @@ watch(
|
||||
const onOk = async () => {
|
||||
const values = await handleSubmit(scheme, formState.value);
|
||||
|
||||
const res = await postAlertMember({
|
||||
const res = await postEditCarbonValue({
|
||||
...values,
|
||||
"building_guid":store.selectedBuilding.building_guid,
|
||||
});
|
||||
if (res.isSuccess) {
|
||||
props.fetchData();
|
||||
props.getData();
|
||||
closeModal();
|
||||
} else {
|
||||
openToast("error", res.msg, "#carbon_emission_item");
|
||||
}
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
carbon_emission_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
carbon_emission_item.close();
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
SaveCheckAuth.value = [];
|
||||
handleErrorReset();
|
||||
props.onCancel();
|
||||
onCancel();
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -67,17 +73,16 @@ const closeModal = () => {
|
||||
<Modal
|
||||
id="carbon_emission_item"
|
||||
:title="t('energy.edit_carbon_emission')"
|
||||
:open="open"
|
||||
:onCancel="closeModal"
|
||||
width="300"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="mt-5 flex flex-col items-center">
|
||||
<Input :value="formState" class="w-full" name="factor">
|
||||
<Input :value="formState" class="w-full" name="coefficient">
|
||||
<template #topLeft>{{$t('energy.carbon_emission_coefficient')}}</template>
|
||||
<template #bottomLeft>
|
||||
<span class="text-error text-base">
|
||||
{{ formErrorMsg.factor }}
|
||||
{{ formErrorMsg.coefficient }}
|
||||
</span>
|
||||
</template>
|
||||
</Input>
|
||||
|
@ -1,11 +1,14 @@
|
||||
<script setup>
|
||||
import LineChart from "@/components/chart/LineChart.vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted,watch } from "vue";
|
||||
import ImmediateDemandModal from "./ImmediateDemandModal.vue";
|
||||
import { getDemand } from "@/apis/energy";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
const editRecord = ref(null);
|
||||
const demandData = ref(null);
|
||||
// 假資料
|
||||
const data = {
|
||||
categories: [
|
||||
@ -111,27 +114,22 @@ const defaultChartOption = ref({
|
||||
series: data.series,
|
||||
});
|
||||
|
||||
const openModal = (record) => {
|
||||
if (record) {
|
||||
editRecord.value = record;
|
||||
} else {
|
||||
editRecord.value = null;
|
||||
const getData = async () => {
|
||||
if (store.selectedBuilding.building_guid) {
|
||||
const res = await getDemand(store.selectedBuilding.building_guid);
|
||||
demandData.value = res.data[0];
|
||||
}
|
||||
immediate_demand_add_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
editRecord.value = null;
|
||||
immediate_demand_add_item.close();
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
console.log("ok");
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
//
|
||||
});
|
||||
watch(
|
||||
() => store.selectedBuilding,
|
||||
(newBuilding) => {
|
||||
if (newBuilding) {
|
||||
getData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -145,12 +143,7 @@ onMounted(() => {
|
||||
{{ $t("energy.average_demand") }}
|
||||
<span class="text-2xl px-2.5">230.8 kw</span>
|
||||
</div>
|
||||
<ImmediateDemandModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
:editRecord="editRecord"
|
||||
:fetchData="fetchData"
|
||||
/>
|
||||
<ImmediateDemandModal :demandData="demandData" :getData="getData" />
|
||||
</div>
|
||||
<LineChart
|
||||
id="immediate_demand_chart"
|
||||
|
@ -1,22 +1,22 @@
|
||||
<script setup>
|
||||
import { inject, defineProps, watch, ref } from "vue";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import { postAlertMember } from "@/apis/alert";
|
||||
import { postEditDemand } from "@/apis/energy";
|
||||
import * as yup from "yup";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
const props = defineProps({
|
||||
openModal: Function,
|
||||
onCancel: Function,
|
||||
editRecord: Object,
|
||||
fetchData: Function,
|
||||
demandData: Object,
|
||||
getData: Function,
|
||||
});
|
||||
|
||||
let scheme = yup.object({
|
||||
contract: yup.number().required(t("button.required")),
|
||||
alert:yup.number().required(t("button.required")),
|
||||
reset:yup.number().required(t("button.required")),
|
||||
alert: yup.number().required(t("button.required")),
|
||||
reset: yup.number().required(t("button.required")),
|
||||
});
|
||||
|
||||
const form = ref(null);
|
||||
@ -26,14 +26,12 @@ const formState = ref({
|
||||
reset: null,
|
||||
});
|
||||
|
||||
const SaveCheckAuth = ref([]);
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset } = useFormErrorMessage(
|
||||
scheme.value
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.editRecord,
|
||||
() => props.demandData,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
formState.value = {
|
||||
@ -46,11 +44,12 @@ watch(
|
||||
const onOk = async () => {
|
||||
const values = await handleSubmit(scheme, formState.value);
|
||||
|
||||
const res = await postAlertMember({
|
||||
const res = await postEditDemand({
|
||||
...values,
|
||||
"building_guid":store.selectedBuilding.building_guid,
|
||||
});
|
||||
if (res.isSuccess) {
|
||||
props.fetchData();
|
||||
props.getData();
|
||||
closeModal();
|
||||
} else {
|
||||
openToast("error", res.msg, "#immediate_demand_add_item");
|
||||
@ -58,27 +57,36 @@ const onOk = async () => {
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
SaveCheckAuth.value = [];
|
||||
handleErrorReset();
|
||||
props.onCancel();
|
||||
onCancel();
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
immediate_demand_add_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
immediate_demand_add_item.close();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="btn btn-sm btn-success ms-auto me-6 my-3" @click.stop.prevent="openModal">
|
||||
<button
|
||||
class="btn btn-sm btn-success ms-auto me-6 my-3"
|
||||
@click.stop.prevent="openModal"
|
||||
>
|
||||
{{ $t("button.edit") }}
|
||||
</button>
|
||||
<Modal
|
||||
id="immediate_demand_add_item"
|
||||
:title="t('energy.edit_automatic_demand')"
|
||||
:open="open"
|
||||
:onCancel="closeModal"
|
||||
width="300"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="mt-5 flex flex-col items-center">
|
||||
<Input :value="formState" class="w-full" name="contract">
|
||||
<template #topLeft>{{$t("energy.contract_capacity")}}</template>
|
||||
<template #topLeft>{{ $t("energy.contract_capacity") }}</template>
|
||||
<template #bottomLeft>
|
||||
<span class="text-error text-base">
|
||||
{{ formErrorMsg.contract }}
|
||||
@ -86,7 +94,7 @@ const closeModal = () => {
|
||||
</template>
|
||||
</Input>
|
||||
<Input class="w-full" :value="formState" name="alert">
|
||||
<template #topLeft>{{$t("energy.alert_capacity")}}</template>
|
||||
<template #topLeft>{{ $t("energy.alert_capacity") }}</template>
|
||||
<template #bottomLeft>
|
||||
<span class="text-error text-base">
|
||||
{{ formErrorMsg.alert }}
|
||||
@ -94,7 +102,7 @@ const closeModal = () => {
|
||||
</template>
|
||||
</Input>
|
||||
<Input class="w-full" :value="formState" name="reset">
|
||||
<template #topLeft>{{$t("energy.reset_value")}}</template>
|
||||
<template #topLeft>{{ $t("energy.reset_value") }}</template>
|
||||
<template #bottomLeft>
|
||||
<span class="text-error text-base">
|
||||
{{ formErrorMsg.reset }}
|
||||
|
@ -6,6 +6,8 @@ import Dept from "./components/Dept.vue";
|
||||
import ElecType from "./components/ElecType.vue";
|
||||
import Vendor from "./components/Vendor.vue";
|
||||
import Floors from "./components/Floors.vue";
|
||||
import Building from "./components/Building.vue";
|
||||
import ElecPriceManagement from "./components/ElecPriceManagement.vue";
|
||||
import MITTList from "./components/MITTList.vue";
|
||||
|
||||
const route = useRoute();
|
||||
@ -14,23 +16,21 @@ const currentComponent = ref(null);
|
||||
const updateComponent = () => {
|
||||
const { main_system_id, sub_system_id } = route.params;
|
||||
|
||||
if (main_system_id === "Setting") {
|
||||
if (sub_system_id === "Department") {
|
||||
currentComponent.value = Dept;
|
||||
} else if(sub_system_id === "ElecType") {
|
||||
currentComponent.value = ElecType;
|
||||
} else if(sub_system_id === "Vendor") {
|
||||
currentComponent.value = Vendor;
|
||||
} else if(sub_system_id === "Floor") {
|
||||
currentComponent.value = Floors;
|
||||
}else{
|
||||
currentComponent.value = MITTList;
|
||||
}
|
||||
} else if (main_system_id === "MQTT") {
|
||||
if (sub_system_id === "Department") {
|
||||
currentComponent.value = Dept;
|
||||
} else if (sub_system_id === "ElecType") {
|
||||
currentComponent.value = ElecType;
|
||||
} else if (sub_system_id === "Vendor") {
|
||||
currentComponent.value = Vendor;
|
||||
} else if (sub_system_id === "Floor") {
|
||||
currentComponent.value = Floors;
|
||||
} else if (sub_system_id === "Building") {
|
||||
currentComponent.value = Building;
|
||||
} else if (sub_system_id === "ElecPricing") {
|
||||
currentComponent.value = ElecPriceManagement;
|
||||
} else if (sub_system_id === "MQTT_Result") {
|
||||
currentComponent.value = MITTList;
|
||||
} else {
|
||||
currentComponent.value = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(updateComponent);
|
||||
@ -44,4 +44,4 @@ watch(
|
||||
</script>
|
||||
<template>
|
||||
<component :is="currentComponent" />
|
||||
</template>
|
||||
</template>
|
||||
|
107
src/views/setting/components/Building.vue
Normal file
107
src/views/setting/components/Building.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<script setup>
|
||||
import Table from "@/components/customUI/Table.vue";
|
||||
import BuildingModal from "./BuildingModal.vue";
|
||||
import { getBuildings, deleteBuildings } from "@/apis/building";
|
||||
import { onMounted, ref, inject, computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { openToast, cancelToastOpen } = inject("app_toast");
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
title: t("accountManagement.index"),
|
||||
key: "index",
|
||||
},
|
||||
{
|
||||
title: t("assetManagement.building"),
|
||||
key: "full_name",
|
||||
filter: true,
|
||||
},
|
||||
{
|
||||
title: t("accountManagement.operation"),
|
||||
key: "operation",
|
||||
},
|
||||
]);
|
||||
|
||||
const dataSource = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const getDataSource = async () => {
|
||||
loading.value = true;
|
||||
const res = await getBuildings();
|
||||
store.buildings = res.data;
|
||||
dataSource.value = res.data.map((d) => ({ ...d, key: d.building_guid }));
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDataSource();
|
||||
});
|
||||
|
||||
const formState = ref({
|
||||
full_name: "",
|
||||
});
|
||||
|
||||
const openModal = (record) => {
|
||||
if (record.building_guid) {
|
||||
formState.value = { ...record };
|
||||
} else {
|
||||
formState.value = {
|
||||
full_name: "",
|
||||
};
|
||||
}
|
||||
build_modal.showModal();
|
||||
};
|
||||
|
||||
const remove = async (building_guid) => {
|
||||
openToast("warning", t("msg.sure_to_delete"), "body", async () => {
|
||||
await cancelToastOpen();
|
||||
const res = await deleteBuildings(building_guid);
|
||||
if (res.isSuccess) {
|
||||
getDataSource();
|
||||
openToast("success", t("msg.delete_success"));
|
||||
} else {
|
||||
openToast("error", res.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-start items-center mt-10 mb-5">
|
||||
<h3 class="text-xl mr-5">{{ $t("assetManagement.building") }}</h3>
|
||||
<BuildingModal
|
||||
:formState="formState"
|
||||
:getData="getDataSource"
|
||||
:openModal="openModal"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Table :columns="columns" :dataSource="dataSource" :loading="loading">
|
||||
<template #bodyCell="{ record, column, index }">
|
||||
<template v-if="column.key === 'index'">{{ index + 1 }}</template>
|
||||
<template v-else-if="column.key === 'operation'">
|
||||
<button
|
||||
class="btn btn-sm btn-success text-white mr-2"
|
||||
@click.stop.prevent="() => openModal(record)"
|
||||
>
|
||||
{{ $t("button.edit") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-error text-white"
|
||||
@click.stop.prevent="() => remove(record.building_guid)"
|
||||
>
|
||||
{{ $t("button.delete") }}
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ record[column.key] }}
|
||||
</template>
|
||||
</template>
|
||||
</Table>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
84
src/views/setting/components/BuildingModal.vue
Normal file
84
src/views/setting/components/BuildingModal.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, defineProps, inject, watch } from "vue";
|
||||
import * as yup from "yup";
|
||||
import "yup-phone-lite";
|
||||
import useFormErrorMessage from "@/hooks/useFormErrorMessage";
|
||||
import { postBuildings } from "@/apis/building";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const { openToast } = inject("app_toast");
|
||||
|
||||
const props = defineProps({
|
||||
formState: Object,
|
||||
getData: Function,
|
||||
openModal: Function
|
||||
});
|
||||
|
||||
const buildScheme = yup.object({
|
||||
full_name: yup.string().required(t("button.required")),
|
||||
});
|
||||
|
||||
const { formErrorMsg, handleSubmit, handleErrorReset, updateScheme } =
|
||||
useFormErrorMessage(buildScheme);
|
||||
|
||||
const onCancel = () => {
|
||||
handleErrorReset();
|
||||
build_modal.close();
|
||||
};
|
||||
|
||||
const onOk = async () => {
|
||||
const value = await handleSubmit(buildScheme, props.formState);
|
||||
const res = await postBuildings(value);
|
||||
if (res.isSuccess) {
|
||||
props.getData();
|
||||
onCancel();
|
||||
} else {
|
||||
openToast("error", res.msg, "#build_modal");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="btn btn-sm btn-add " @click.stop.prevent="props.openModal">
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||
</button>
|
||||
<Modal
|
||||
id="build_modal"
|
||||
:title="props.formState?.building_guid ? t('button.edit') : t('button.add')"
|
||||
:onCancel="onCancel"
|
||||
width="400"
|
||||
>
|
||||
<template #modalContent>
|
||||
<form ref="form" class="mt-5 w-full flex flex-wrap justify-between">
|
||||
<Input :value="formState" class="my-2" name="full_name">
|
||||
<template #topLeft>{{
|
||||
$t("assetManagement.building")
|
||||
}}</template>
|
||||
<template #bottomLeft
|
||||
><span class="text-error text-base">
|
||||
{{ formErrorMsg.full_name }}
|
||||
</span></template
|
||||
></Input
|
||||
>
|
||||
</form>
|
||||
</template>
|
||||
<template #modalAction>
|
||||
<button
|
||||
type="reset"
|
||||
class="btn btn-outline-success mr-2"
|
||||
@click.prevent="onCancel"
|
||||
>
|
||||
{{ $t("button.cancel") }}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-outline-success"
|
||||
@click.stop.prevent="onOk"
|
||||
>
|
||||
{{ $t("button.submit") }}
|
||||
</button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
105
src/views/setting/components/ElecPriceManagement.vue
Normal file
105
src/views/setting/components/ElecPriceManagement.vue
Normal file
@ -0,0 +1,105 @@
|
||||
<script setup>
|
||||
import ButtonGroup from "@/components/customUI/ButtonGroup.vue";
|
||||
import ElecPriceRes from "./ElecPriceRes.vue";
|
||||
import ElecPriceStd from "./ElecPriceStd.vue";
|
||||
import { computed, watch, onBeforeMount, ref, provide } from "vue";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { getTimeElec } from "@/apis/energy";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t, locale } = useI18n();
|
||||
const sim2 = ref([]);
|
||||
const sim3 = ref([]);
|
||||
const stand2 = ref([]);
|
||||
const stand3 = ref([]);
|
||||
|
||||
const changeComponent = (e, item) => {
|
||||
changeActiveBtn(item);
|
||||
};
|
||||
|
||||
const { items, changeActiveBtn, setItems } = useActiveBtn();
|
||||
|
||||
const initializeItems = () => {
|
||||
setItems([
|
||||
{
|
||||
title: t("energy.residential"),
|
||||
key: "Residential",
|
||||
active: true,
|
||||
component: ElecPriceRes,
|
||||
},
|
||||
{
|
||||
title: t("energy.standard"),
|
||||
key: "Standard",
|
||||
active: false,
|
||||
component: ElecPriceStd,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
initializeItems();
|
||||
});
|
||||
|
||||
const activeTab = computed(() => {
|
||||
return items.value.find(({ active }) => active);
|
||||
});
|
||||
|
||||
const getData = async () => {
|
||||
if (store.selectedBuilding.building_guid) {
|
||||
const res = await getTimeElec(store.selectedBuilding.building_guid);
|
||||
|
||||
// 重置 ref 變數
|
||||
sim2.value = [];
|
||||
sim3.value = [];
|
||||
stand2.value = [];
|
||||
stand3.value = [];
|
||||
|
||||
res.data.forEach((item) => {
|
||||
switch (item.sheet) {
|
||||
case "sim2":
|
||||
sim2.value = item.data;
|
||||
break;
|
||||
case "sim3":
|
||||
sim3.value = item.data;
|
||||
break;
|
||||
case "stand2":
|
||||
stand2.value = item.data;
|
||||
break;
|
||||
case "stand3":
|
||||
stand3.value = item.data;
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown sheet: ${item.sheet}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => store.selectedBuilding,
|
||||
(newBuilding) => {
|
||||
if (newBuilding) {
|
||||
getData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
provide("time_elec", { sim2, sim3, stand2, stand3, getData });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="text-2xl font-extrabold mb-2">
|
||||
{{ $t("energy.elec_price_list") }}
|
||||
</h1>
|
||||
<ButtonGroup
|
||||
:items="items"
|
||||
:withLine="true"
|
||||
class="my-6"
|
||||
:onclick="changeComponent"
|
||||
/>
|
||||
<component :is="activeTab.component"></component>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
366
src/views/setting/components/ElecPriceRes.vue
Normal file
366
src/views/setting/components/ElecPriceRes.vue
Normal file
@ -0,0 +1,366 @@
|
||||
<script setup>
|
||||
import { computed, inject, watch, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { postTimeElec } from "@/apis/energy";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { sim2, sim3, getData } = inject("time_elec");
|
||||
const sim2isEditing = ref(false);
|
||||
const sim3isEditing = ref(false);
|
||||
const sim2NewValue = ref([]);
|
||||
const sim3NewValue = ref([]);
|
||||
const onOk = async (sheet, data) => {
|
||||
const res = await postTimeElec({
|
||||
sheet: sheet,
|
||||
cost: data,
|
||||
building_guid: store.selectedBuilding.building_guid,
|
||||
});
|
||||
if (res.isSuccess) {
|
||||
getData();
|
||||
onCancel(sheet);
|
||||
} else {
|
||||
openToast("error", res.msg, "#immediate_demand_add_item");
|
||||
}
|
||||
};
|
||||
|
||||
const onCancel = (sheet) => {
|
||||
if (sheet === "sim2") {
|
||||
sim2isEditing.value = false;
|
||||
sim2NewValue.value = [...sim2.value];
|
||||
} else if (sheet === "sim3") {
|
||||
sim3isEditing.value = false;
|
||||
sim3NewValue.value = [...sim3.value];
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
sim2,
|
||||
(newValue, oldValue) => {
|
||||
sim2NewValue.value = [...newValue];
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
sim3,
|
||||
(newValue, oldValue) => {
|
||||
sim3NewValue.value = [...newValue];
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-start items-center my-5">
|
||||
<h3 class="text-xl mr-5">簡易型時間電價二段式</h3>
|
||||
<button
|
||||
v-if="!sim2isEditing"
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.stop.prevent="sim2isEditing = true"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" />{{
|
||||
$t("button.start_edit")
|
||||
}}
|
||||
</button>
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.prevent="onOk('sim2', sim2NewValue)"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'save']" />{{ $t("button.confirm") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-info mr-3"
|
||||
@click.stop.prevent="onCancel('sim2')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'times']" />{{ $t("button.cancel") }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<table class="">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="6" class="bg-teal-800 bg-opacity-20">分類</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">夏月<br />(6/1~9/30)</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">非夏月<br />(夏月以外的時間)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="bg-teal-800 bg-opacity-40">基本電費</td>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">按戶計收</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">每戶每月</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[0]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="6">流動電費</td>
|
||||
<td rowspan="4">週一~週五</td>
|
||||
<td rowspan="2" class="bg-rose-600 bg-opacity-70">尖峰時間</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">09:00 ~ 24:00</td>
|
||||
<td rowspan="5">每度</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[1]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-rose-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
06:00 ~ 11:00<br />14:00 ~ 24:00
|
||||
</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[2]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[3]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
00:00 ~ 06:00<br />11:00 ~ 14:00
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[4]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>週六、週日<br />及離峰日</td>
|
||||
<td class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td colspan="2" class="bg-green-600 bg-opacity-20">全日</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[5]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[6]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">每月總度數超過2000度之部分</td>
|
||||
<td>每度</td>
|
||||
<td colspan="2" class="!text-start">
|
||||
<div class="flex items-center">
|
||||
加
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim2NewValue[7]"
|
||||
:readonly="!sim2isEditing"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="flex justify-start items-center mt-16">
|
||||
<h3 class="text-xl mr-5">簡易型時間電價三段式</h3>
|
||||
<button
|
||||
v-if="!sim3isEditing"
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.stop.prevent="sim3isEditing = true"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" />{{
|
||||
$t("button.start_edit")
|
||||
}}
|
||||
</button>
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.prevent="onOk('sim3', sim3NewValue)"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'save']" />{{ $t("button.confirm") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-info mr-3"
|
||||
@click.stop.prevent="onCancel('sim3')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'times']" />{{ $t("button.cancel") }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<table class="my-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="6" class="bg-teal-800 bg-opacity-20">分類</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">夏月<br />(6/1~9/30)</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">非夏月<br />(夏月以外的時間)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="bg-teal-800 bg-opacity-40">基本電費</td>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">按戶計收</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">每戶每月</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[0]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="7">流動電費</td>
|
||||
<td rowspan="5">週一~週五</td>
|
||||
<td class="bg-rose-600 bg-opacity-70">尖峰時間</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">16:00 ~ 22:00</td>
|
||||
<td rowspan="6">每度</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[1]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-yellow-400 bg-opacity-80">半尖峰時間</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">夏月</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
09:00 ~ 16:00<br />22:00~24:00
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[2]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-yellow-500 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
06:00 ~ 11:00<br />14:00 ~ 24:00
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[3]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[4]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
00:00 ~ 06:00<br />11:00 ~ 14:00
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[5]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>週六、週日<br />及離峰日</td>
|
||||
<td colspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">全日</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[6]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[7]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4">每月總度數超過2000度之部分</td>
|
||||
<td>每度</td>
|
||||
<td colspan="2" class="!text-start">
|
||||
<div class="flex items-center">
|
||||
加
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="sim3NewValue[8]"
|
||||
:readonly="!sim3isEditing"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
th,
|
||||
td {
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.75rem;
|
||||
text-align: center;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input {
|
||||
@apply text-lg text-white w-full bg-transparent input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:text-white read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0;
|
||||
}
|
||||
</style>
|
597
src/views/setting/components/ElecPriceStd.vue
Normal file
597
src/views/setting/components/ElecPriceStd.vue
Normal file
@ -0,0 +1,597 @@
|
||||
<script setup>
|
||||
import { computed, inject, watch, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { postTimeElec } from "@/apis/energy";
|
||||
import useBuildingStore from "@/stores/useBuildingStore";
|
||||
const store = useBuildingStore();
|
||||
const { t } = useI18n();
|
||||
const { stand2, stand3, getData } = inject("time_elec");
|
||||
const stand2isEditing = ref(false);
|
||||
const stand3isEditing = ref(false);
|
||||
const stand2NewValue = ref([]);
|
||||
const stand3NewValue = ref([]);
|
||||
const onOk = async (sheet, data) => {
|
||||
const res = await postTimeElec({
|
||||
sheet: sheet,
|
||||
cost: data,
|
||||
building_guid: store.selectedBuilding.building_guid,
|
||||
});
|
||||
if (res.isSuccess) {
|
||||
getData();
|
||||
onCancel(sheet);
|
||||
} else {
|
||||
openToast("error", res.msg, "#immediate_demand_add_item");
|
||||
}
|
||||
};
|
||||
|
||||
const onCancel = (sheet) => {
|
||||
if (sheet === "stand2") {
|
||||
stand2isEditing.value = false;
|
||||
stand2NewValue.value = [...stand2.value];
|
||||
} else if (sheet === "stand3") {
|
||||
stand3isEditing.value = false;
|
||||
stand3NewValue.value = [...stand3.value];
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
stand2,
|
||||
(newValue, oldValue) => {
|
||||
stand2NewValue.value = [...newValue];
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
stand3,
|
||||
(newValue, oldValue) => {
|
||||
stand3NewValue.value = [...newValue];
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-start items-center my-5">
|
||||
<h3 class="text-xl mr-5">標準型時間電價二段式</h3>
|
||||
<button
|
||||
v-if="!stand2isEditing"
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.stop.prevent="stand2isEditing = true"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" />{{
|
||||
$t("button.start_edit")
|
||||
}}
|
||||
</button>
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.prevent="onOk('stand2', stand2NewValue)"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'save']" />{{ $t("button.confirm") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-info mr-3"
|
||||
@click.stop.prevent="onCancel('stand2')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'times']" />{{ $t("button.cancel") }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<table class="">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="6" class="bg-teal-800 bg-opacity-20">分類</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">夏月<br />(6/1~9/30)</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">非夏月<br />(夏月以外的時間)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="6" class="bg-teal-800 bg-opacity-40">基本電費</td>
|
||||
<td colspan="2" rowspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
按戶計收
|
||||
</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">單相</td>
|
||||
<td rowspan="2" class="bg-teal-800 bg-opacity-40">每戶每月</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[0]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">三相</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[1]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">經常契約</td>
|
||||
<td rowspan="4" class="bg-teal-800 bg-opacity-40">每瓩每月</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[2]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[3]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">非夏日契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">-</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[4]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">週六半尖峰契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[5]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[6]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">離峰契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[7]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[8]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="9">流動電費</td>
|
||||
<td rowspan="4">週一~週五</td>
|
||||
<td rowspan="2" class="bg-rose-600 bg-opacity-70">尖峰時間</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">09:00 ~ 24:00</td>
|
||||
<td rowspan="9">每度</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[9]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-rose-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">06:00 ~ 11:00<br />14:00~24:00</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[10]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[11]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
00:00 ~ 06:00<br />
|
||||
11:00 ~ 14:00
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[12]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="4">週六</td>
|
||||
<td rowspan="2" class="bg-yellow-400 bg-opacity-80">半尖峰時間</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">夏日</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">09:00 ~ 24:00</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[13]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-yellow-400 bg-opacity-20">非夏日</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">
|
||||
06:00 ~ 11:00<br />
|
||||
14:00 ~ 24:00
|
||||
</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">-</td>
|
||||
<td class="bg-yellow-400 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[14]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[15]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 06:00<br />11:00 ~ 14:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[16]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>週六、週日<br />及離峰日</td>
|
||||
<td class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td colspan="2" class="bg-green-600 bg-opacity-20">全日</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[17]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand2NewValue[18]"
|
||||
:readonly="!stand2isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="flex justify-start items-center mt-14">
|
||||
<h3 class="text-xl mr-5">標準型時間電價三段式</h3>
|
||||
<button
|
||||
v-if="!stand3isEditing"
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.stop.prevent="stand3isEditing = true"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'pencil-alt']" />{{
|
||||
$t("button.start_edit")
|
||||
}}
|
||||
</button>
|
||||
<template v-else>
|
||||
<button
|
||||
class="btn btn-sm btn-add mr-3"
|
||||
@click.prevent="onOk('stand3', stand3NewValue)"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'save']" />{{ $t("button.confirm") }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-info mr-3"
|
||||
@click.stop.prevent="onCancel('stand3')"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'times']" />{{ $t("button.cancel") }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<table class="my-5">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="6" class="bg-teal-800 bg-opacity-20">分類</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">夏月<br />(6/1~9/30)</th>
|
||||
<th class="bg-teal-800 bg-opacity-20">非夏月<br />(夏月以外的時間)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="6" class="bg-teal-800 bg-opacity-40">基本電費</td>
|
||||
<td colspan="2" rowspan="2" class="bg-teal-800 bg-opacity-40">按戶計收</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">單相</td>
|
||||
<td rowspan="2" class="bg-teal-800 bg-opacity-40">每戶每月</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[0]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">三相</td>
|
||||
<td colspan="2" class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[1]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">經常契約</td>
|
||||
<td rowspan="4" class="bg-teal-800 bg-opacity-40">每瓩每月</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[2]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[3]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">非夏日契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[4]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[5]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">週六半尖峰契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[6]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[7]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="bg-teal-800 bg-opacity-40">離峰契約</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[8]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-teal-800 bg-opacity-40">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[9]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="10">流動電費</td>
|
||||
<td rowspan="5">週一~週五</td>
|
||||
<td class="bg-rose-600 bg-opacity-70">尖峰時間</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">16:00 ~ 22:00</td>
|
||||
<td rowspan="10">每度</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[10]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-rose-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-yellow-400 bg-opacity-80">半尖峰時間</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">夏月</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">09:00 ~ 16:00<br />22:00 ~ 24:00</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[11]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-yellow-500 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">06:00 ~ 11:00<br />14:00 ~ 24:00</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[12]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[13]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
00:00 ~ 06:00<br />
|
||||
11:00 ~ 14:00
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[14]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="4">週六</td>
|
||||
<td rowspan="2" class="bg-yellow-400 bg-opacity-80">半尖峰時間</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">夏日</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">09:00 ~ 24:00</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[15]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-yellow-500 bg-opacity-20">非夏日</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
06:00 ~ 11:00<br />
|
||||
14:00 ~ 24:00
|
||||
</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">-</td>
|
||||
<td class="bg-yellow-500 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[16]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2" class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td class="bg-green-600 bg-opacity-20">夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 09:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[17]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-green-600 bg-opacity-20">非夏月</td>
|
||||
<td class="bg-green-600 bg-opacity-20">00:00 ~ 06:00<br />11:00 ~ 14:00</td>
|
||||
<td class="bg-green-600 bg-opacity-20">-</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[18]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>週日及離峰日</td>
|
||||
<td class="bg-green-600 bg-opacity-60">離峰時間</td>
|
||||
<td colspan="2" class="bg-green-600 bg-opacity-20">全日</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[19]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
<td class="bg-green-600 bg-opacity-20">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="stand3NewValue[20]"
|
||||
:readonly="!stand3isEditing"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
th,
|
||||
td {
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.5rem 0.75rem;
|
||||
text-align: center;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
input {
|
||||
@apply text-lg text-white w-full bg-transparent input input-bordered rounded-md px-3 border-info focus-within:border-info read-only:text-white read-only:border-0 read-only:focus-within:outline-0 read-only:focus:outline-0;
|
||||
}
|
||||
</style>
|
91
src/views/setting/components/MITTCheckboxTree.vue
Normal file
91
src/views/setting/components/MITTCheckboxTree.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<script setup>
|
||||
import { defineProps, defineEmits } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
checkedNodes: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:checkedNodes"]);
|
||||
|
||||
const toggleExpand = (node) => {
|
||||
node.expanded = !node.expanded;
|
||||
};
|
||||
|
||||
const isChecked = (node) => {
|
||||
return props.checkedNodes.includes(node.value);
|
||||
};
|
||||
|
||||
const isIndeterminate = (node) => {
|
||||
if (!node.children?.length) return false;
|
||||
|
||||
const hasCheckedChild = node.children.some(child =>
|
||||
isChecked(child) || isIndeterminate(child)
|
||||
);
|
||||
const allChildrenChecked = node.children.every(child => isChecked(child));
|
||||
|
||||
return hasCheckedChild && !allChildrenChecked;
|
||||
};
|
||||
|
||||
const toggleNode = (node, checked) => {
|
||||
const newCheckedNodes = new Set(props.checkedNodes);
|
||||
|
||||
const processNode = (currentNode) => {
|
||||
if (checked) {
|
||||
newCheckedNodes.add(currentNode.value);
|
||||
} else {
|
||||
newCheckedNodes.delete(currentNode.value);
|
||||
}
|
||||
|
||||
currentNode.children?.forEach(child => {
|
||||
processNode(child);
|
||||
});
|
||||
};
|
||||
|
||||
processNode(node);
|
||||
emit("update:checkedNodes", Array.from(newCheckedNodes));
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul class="pl-4 text-white ">
|
||||
<li v-for="node in data" :key="node.value" class="mb-2">
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
v-if="node.children?.length"
|
||||
@click="toggleExpand(node)"
|
||||
class="cursor-pointer mr-2 w-4 inline-block"
|
||||
>
|
||||
{{ node.expanded ? '▼' : '▶' }}
|
||||
</span>
|
||||
<span v-else class="w-4 mr-2"></span>
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="isChecked(node)"
|
||||
:indeterminate="isIndeterminate(node)"
|
||||
@change="toggleNode(node, $event.target.checked)"
|
||||
class="mr-2"
|
||||
/>
|
||||
|
||||
<span class="cursor-pointer" @click="toggleNode(node, !isChecked(node))">
|
||||
{{ node.label }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<MITTCheckboxTree
|
||||
v-if="node.children?.length && node.expanded"
|
||||
:data="node.children"
|
||||
:checked-nodes="checkedNodes"
|
||||
@update:checked-nodes="$emit('update:checkedNodes', $event)"
|
||||
class="mt-2"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
@ -2,6 +2,7 @@
|
||||
import { ref, onMounted, watch, computed } from "vue";
|
||||
import { getAssetMainList, getAssetSubList, getIOTSchema } from "@/apis/asset";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import MITTlISTAddModal from "./MITTlISTAddModal.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const formState = ref({});
|
||||
@ -74,6 +75,15 @@ const getDataSource = async (id) => {
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const openModal = () => {
|
||||
MQTT_Parse_item.showModal();
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
MQTT_Parse_item.close();
|
||||
getDataSource(parseInt(selectedSubSysItems.key))
|
||||
};
|
||||
|
||||
watch(
|
||||
selectedMainSysItems,
|
||||
(newValue) => {
|
||||
@ -133,6 +143,13 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-start items-center mt-5 mb-2">
|
||||
<h3 class="text-xl mr-5">MQTT_Parse : </h3>
|
||||
<MITTlISTAddModal
|
||||
:openModal="openModal"
|
||||
:onCancel="onCancel"
|
||||
/>
|
||||
</div>
|
||||
<Table
|
||||
:columns="columns"
|
||||
:dataSource="dataSource"
|
||||
|
235
src/views/setting/components/MITTlISTAddModal.vue
Normal file
235
src/views/setting/components/MITTlISTAddModal.vue
Normal file
@ -0,0 +1,235 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, watch, defineProps } from "vue";
|
||||
import { getAssetMainList, getAssetSubList, getIOTSchema } from "@/apis/asset";
|
||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||
import MITTCheckboxTree from "./MITTCheckboxTree.vue";
|
||||
import generateSchema from "json-schema-generator";
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
openModal: Function,
|
||||
onCancel: Function,
|
||||
});
|
||||
// 新增:將 jsonInput 與結構資料初始化
|
||||
const jsonInput = ref("");
|
||||
const treeData = ref(null);
|
||||
const checkedNodes = ref([]);
|
||||
|
||||
const form = ref(null);
|
||||
const schemaName = ref("");
|
||||
const formStates = ref([]);
|
||||
const optionData = ref([
|
||||
{ key: 0, full_name: "否" },
|
||||
{ key: 1, full_name: "是" },
|
||||
]);
|
||||
|
||||
// JSON Schema 轉換
|
||||
const customGenerateSchema = (json) => {
|
||||
if (typeof json !== "object" || json === null) return {};
|
||||
|
||||
const schema = { type: "object", properties: {} };
|
||||
Object.entries(json).forEach(([key, value]) => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
schema.properties[key] = customGenerateSchema(value);
|
||||
} else {
|
||||
schema.properties[key] = { type: typeof value };
|
||||
}
|
||||
});
|
||||
|
||||
return schema;
|
||||
};
|
||||
|
||||
// 將提取的架構轉換為 Tree 結構
|
||||
const transformToTree = (schema, parentPath = "") => {
|
||||
if (typeof schema !== "object" || schema === null) return [];
|
||||
|
||||
return Object.entries(schema)
|
||||
.map(([key, value]) => {
|
||||
const currentPath = parentPath ? `${parentPath}_${key}` : key;
|
||||
const isObject = typeof value === "object" && value !== null;
|
||||
|
||||
if (isObject && value.properties) {
|
||||
return {
|
||||
label: key,
|
||||
value: currentPath,
|
||||
expanded: true,
|
||||
children: transformToTree(value.properties, currentPath),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
label: key,
|
||||
value: currentPath,
|
||||
expanded: true,
|
||||
children: [],
|
||||
};
|
||||
})
|
||||
.filter((item) => item !== null); // 過濾掉 null 值
|
||||
};
|
||||
|
||||
// 解析 JSON 並生成樹狀結構
|
||||
const parseJson = () => {
|
||||
try {
|
||||
const json = JSON.parse(jsonInput.value);
|
||||
|
||||
// 解析 JSON 結構
|
||||
const schema = customGenerateSchema(json);
|
||||
console.log("JSON Schema:", schema);
|
||||
|
||||
// 進行結構轉換並顯示
|
||||
treeData.value = transformToTree(schema.properties);
|
||||
console.log("轉換後的樹狀結構:", treeData.value);
|
||||
} catch (error) {
|
||||
console.error("JSON 格式不正確:", error);
|
||||
alert("請檢查 JSON 格式,確保它是有效的!");
|
||||
}
|
||||
};
|
||||
|
||||
const clearAll = () => {
|
||||
jsonInput.value = ""; // 清空輸入的 JSON
|
||||
treeData.value = null; // 清除生成的樹狀結構
|
||||
checkedNodes.value = []; // 清空已勾選的節點
|
||||
};
|
||||
|
||||
watch(
|
||||
() => checkedNodes.value,
|
||||
(newCheckedNodes) => {
|
||||
// 為每個 node 創建一個 formState
|
||||
formStates.value = newCheckedNodes.map((node) => ({
|
||||
IoT_point_schema: node,
|
||||
sys_point_name: null,
|
||||
is_bool: 1,
|
||||
decimal: 0,
|
||||
is_open: 1,
|
||||
}));
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button class="btn btn-sm btn-add mr-3" @click.stop.prevent="openModal">
|
||||
<font-awesome-icon :icon="['fas', 'plus']" />{{ $t("button.add") }}
|
||||
</button>
|
||||
<Modal
|
||||
id="MQTT_Parse_item"
|
||||
title="MQTT_Parse"
|
||||
:open="open"
|
||||
:onCancel="onCancel"
|
||||
width="1600"
|
||||
>
|
||||
<template #modalContent>
|
||||
<div class="flex w-full gap-4 mt-5">
|
||||
<div class="w-1/2 relative">
|
||||
<textarea
|
||||
v-model="jsonInput"
|
||||
placeholder="請貼上 JSON 格式數據"
|
||||
class="w-full h-[500px] p-4 border rounded-lg font-mono text-white"
|
||||
></textarea>
|
||||
<button @click="clearAll" class="bg-error btn absolute top-5 right-5">
|
||||
<font-awesome-icon :icon="['fas', 'trash-alt']" />
|
||||
</button>
|
||||
</div>
|
||||
<button @click="parseJson" class="btn-success btn my-auto">
|
||||
轉換
|
||||
<font-awesome-icon
|
||||
:icon="['fas', 'chevron-right']"
|
||||
size="lg"
|
||||
class="block"
|
||||
/>
|
||||
</button>
|
||||
<div class="w-1/2 p-4 rounded-lg border overflow-y-scroll h-[500px]">
|
||||
<MITTCheckboxTree
|
||||
v-if="treeData"
|
||||
:data="treeData"
|
||||
v-model:checked-nodes="checkedNodes"
|
||||
/>
|
||||
<div v-else class="text-white">請在左側輸入 JSON 並點擊轉換按鈕</div>
|
||||
</div>
|
||||
</div>
|
||||
<form ref="form" class="">
|
||||
<div class="flex items-center mt-5">
|
||||
<h2 class="text-lg font-bold whitespace-nowrap me-2">
|
||||
結構名稱 :
|
||||
</h2>
|
||||
<Input v-model="schemaName" />
|
||||
</div>
|
||||
<table class="table" v-if="checkedNodes.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IoT 點位名稱</th>
|
||||
<th>IoT 點位結構</th>
|
||||
<th>系統點位名稱</th>
|
||||
<th>bool 值</th>
|
||||
<th>小數點個數</th>
|
||||
<th>點位開關</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(node, index) in checkedNodes" :key="node">
|
||||
<td>
|
||||
<Input :value="formStates[index]" name="IoT_point_name" />
|
||||
</td>
|
||||
<td>
|
||||
<Input
|
||||
:value="formStates[index]"
|
||||
name="IoT_point_schema"
|
||||
:readonly="true"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<select>
|
||||
<option value="option1">選項 1</option>
|
||||
<option value="option2">選項 2</option>
|
||||
<option value="option3">選項 3</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex w-36">
|
||||
<Select
|
||||
:value="formStates[index]"
|
||||
selectClass="w-20 mx-auto border-info focus-within:border-info"
|
||||
name="is_bool"
|
||||
Attribute="full_name"
|
||||
:options="optionData"
|
||||
>
|
||||
</Select>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<InputNumber
|
||||
:value="formStates[index]"
|
||||
class="mx-auto"
|
||||
name="decimal"
|
||||
>
|
||||
</InputNumber>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex w-36">
|
||||
<Select
|
||||
:value="formStates[index]"
|
||||
selectClass="w-20 mx-auto border-info focus-within:border-info"
|
||||
name="is_open"
|
||||
Attribute="full_name"
|
||||
:options="optionData"
|
||||
>
|
||||
</Select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.table th {
|
||||
@apply bg-cyan-600 bg-opacity-30 border border-white text-lg font-semibold text-white text-center px-2 py-3;
|
||||
}
|
||||
|
||||
.table td {
|
||||
@apply border border-white text-lg font-semibold text-white text-center px-2 py-3;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user