Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d128e35907 |
@@ -6,7 +6,6 @@ ENV = 'development'
|
|||||||
|
|
||||||
#开发环境
|
#开发环境
|
||||||
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
||||||
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
|
||||||
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
||||||
# 路由懒加载
|
# 路由懒加载
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ NODE_ENV = production
|
|||||||
ENV = 'staging'
|
ENV = 'staging'
|
||||||
|
|
||||||
# 测试环境
|
# 测试环境
|
||||||
# VUE_APP_BASE_API = 'http://18.183.240.108:8080/api/'
|
|
||||||
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
VUE_APP_BASE_API = 'https://test.m2pool.com/api/'
|
||||||
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
VUE_APP_BASE_URL = 'https://test.m2pool.com/'
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
520
mining-pool/package-lock.json
generated
520
mining-pool/package-lock.json
generated
@@ -290,45 +290,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/helpers": {
|
"@babel/helpers": {
|
||||||
"version": "7.27.0",
|
"version": "7.26.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
|
||||||
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
|
"integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/template": "^7.27.0",
|
"@babel/template": "^7.26.9",
|
||||||
"@babel/types": "^7.27.0"
|
"@babel/types": "^7.26.9"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/parser": {
|
|
||||||
"version": "7.27.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
|
|
||||||
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/types": "^7.27.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@babel/template": {
|
|
||||||
"version": "7.27.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
|
|
||||||
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/code-frame": "^7.26.2",
|
|
||||||
"@babel/parser": "^7.27.0",
|
|
||||||
"@babel/types": "^7.27.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@babel/types": {
|
|
||||||
"version": "7.27.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
|
|
||||||
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/helper-string-parser": "^7.25.9",
|
|
||||||
"@babel/helper-validator-identifier": "^7.25.9"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/highlight": {
|
"@babel/highlight": {
|
||||||
@@ -1136,9 +1104,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
"version": "7.27.0",
|
"version": "7.26.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz",
|
||||||
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
|
"integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
@@ -1146,18 +1115,11 @@
|
|||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime-corejs3": {
|
|
||||||
"version": "7.28.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.2.tgz",
|
|
||||||
"integrity": "sha512-FVFaVs2/dZgD3Y9ZD+AKNKjyGKzwu0C54laAXWUXgLcVXcCX6YZ6GhK2cp7FogSN2OA0Fu+QT8dP3FUdo9ShSQ==",
|
|
||||||
"requires": {
|
|
||||||
"core-js-pure": "^3.43.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@babel/template": {
|
"@babel/template": {
|
||||||
"version": "7.26.9",
|
"version": "7.26.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
|
||||||
@@ -1336,64 +1298,6 @@
|
|||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@isaacs/cliui": {
|
|
||||||
"version": "8.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
|
||||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
|
||||||
"requires": {
|
|
||||||
"string-width": "^5.1.2",
|
|
||||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
|
||||||
"strip-ansi": "^7.0.1",
|
|
||||||
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
|
|
||||||
"wrap-ansi": "^8.1.0",
|
|
||||||
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "6.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
|
||||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
|
|
||||||
},
|
|
||||||
"emoji-regex": {
|
|
||||||
"version": "9.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
|
||||||
"requires": {
|
|
||||||
"eastasianwidth": "^0.2.0",
|
|
||||||
"emoji-regex": "^9.2.2",
|
|
||||||
"strip-ansi": "^7.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "7.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
|
||||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^6.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrap-ansi": {
|
|
||||||
"version": "8.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
|
||||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^6.1.0",
|
|
||||||
"string-width": "^5.0.1",
|
|
||||||
"strip-ansi": "^7.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@jridgewell/gen-mapping": {
|
"@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.8",
|
"version": "0.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
|
||||||
@@ -1538,11 +1442,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@one-ini/wasm": {
|
|
||||||
"version": "0.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
|
|
||||||
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="
|
|
||||||
},
|
|
||||||
"@parcel/watcher": {
|
"@parcel/watcher": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
||||||
@@ -1710,12 +1609,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@pkgjs/parseargs": {
|
|
||||||
"version": "0.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
|
||||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"@polka/url": {
|
"@polka/url": {
|
||||||
"version": "1.0.0-next.28",
|
"version": "1.0.0-next.28",
|
||||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
|
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
|
||||||
@@ -1825,16 +1718,6 @@
|
|||||||
"integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
|
"integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@stomp/stompjs": {
|
|
||||||
"version": "7.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@stomp/stompjs/-/stompjs-7.1.1.tgz",
|
|
||||||
"integrity": "sha512-chcDs6YkAnKp1FqzwhGvh3i7v0+/ytzqWdKYw6XzINEKAzke/iD00dNgFPWSZEqktHOK+C1gSzXhLkLbARIaZw=="
|
|
||||||
},
|
|
||||||
"@tinymce/tinymce-vue": {
|
|
||||||
"version": "6.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-vue/-/tinymce-vue-6.2.0.tgz",
|
|
||||||
"integrity": "sha512-HiXKB+M3mJnWO6/8kY0HsP255+8zLZw5JMqHKVUvsXvzYyHW+splXXwYDYOkCYqf39R5nBqQaK2l2WL9rz3y5w=="
|
|
||||||
},
|
|
||||||
"@trysound/sax": {
|
"@trysound/sax": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
@@ -2867,11 +2750,6 @@
|
|||||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"abbrev": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ=="
|
|
||||||
},
|
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@@ -3154,9 +3032,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "1.8.4",
|
"version": "1.7.9",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
||||||
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
|
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
@@ -3854,6 +3732,7 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"color-name": "~1.1.4"
|
"color-name": "~1.1.4"
|
||||||
}
|
}
|
||||||
@@ -3861,7 +3740,8 @@
|
|||||||
"color-name": {
|
"color-name": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"colord": {
|
"colord": {
|
||||||
"version": "2.9.3",
|
"version": "2.9.3",
|
||||||
@@ -3998,15 +3878,6 @@
|
|||||||
"typedarray": "^0.0.6"
|
"typedarray": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"config-chain": {
|
|
||||||
"version": "1.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
|
||||||
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
|
|
||||||
"requires": {
|
|
||||||
"ini": "^1.3.4",
|
|
||||||
"proto-list": "~1.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"connect-history-api-fallback": {
|
"connect-history-api-fallback": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
|
||||||
@@ -4115,11 +3986,6 @@
|
|||||||
"browserslist": "^4.24.3"
|
"browserslist": "^4.24.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"core-js-pure": {
|
|
||||||
"version": "3.44.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.44.0.tgz",
|
|
||||||
"integrity": "sha512-gvMQAGB4dfVUxpYD0k3Fq8J+n5bB6Ytl15lqlZrOIXFzxOhtPaObfkQGHtMRdyjIf7z2IeNULwi1jEwyS+ltKQ=="
|
|
||||||
},
|
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
@@ -4712,11 +4578,6 @@
|
|||||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"eastasianwidth": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
|
||||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
|
||||||
},
|
|
||||||
"easy-stack": {
|
"easy-stack": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
|
||||||
@@ -4732,45 +4593,6 @@
|
|||||||
"zrender": "5.6.1"
|
"zrender": "5.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editorconfig": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
|
|
||||||
"requires": {
|
|
||||||
"@one-ini/wasm": "0.1.1",
|
|
||||||
"commander": "^10.0.0",
|
|
||||||
"minimatch": "9.0.1",
|
|
||||||
"semver": "^7.5.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"commander": {
|
|
||||||
"version": "10.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
|
||||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "9.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
|
|
||||||
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"semver": {
|
|
||||||
"version": "7.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
|
||||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ee-first": {
|
"ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@@ -4798,7 +4620,8 @@
|
|||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"emojis-list": {
|
"emojis-list": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
@@ -5610,11 +5433,6 @@
|
|||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fast-diff": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
|
|
||||||
},
|
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||||
@@ -5835,58 +5653,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||||
"integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
|
"integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="
|
||||||
},
|
},
|
||||||
"foreground-child": {
|
|
||||||
"version": "3.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
|
|
||||||
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
|
|
||||||
"requires": {
|
|
||||||
"cross-spawn": "^7.0.6",
|
|
||||||
"signal-exit": "^4.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cross-spawn": {
|
|
||||||
"version": "7.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
||||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
|
||||||
"requires": {
|
|
||||||
"path-key": "^3.1.0",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"which": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path-key": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
|
||||||
},
|
|
||||||
"shebang-command": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
||||||
"requires": {
|
|
||||||
"shebang-regex": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shebang-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
|
||||||
},
|
|
||||||
"signal-exit": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"requires": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||||
@@ -6485,11 +6251,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
"ini": {
|
|
||||||
"version": "1.3.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
|
||||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
|
||||||
},
|
|
||||||
"ipaddr.js": {
|
"ipaddr.js": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
@@ -6585,7 +6346,8 @@
|
|||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
@@ -6678,22 +6440,14 @@
|
|||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"isobject": {
|
"isobject": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||||
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
|
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="
|
||||||
},
|
},
|
||||||
"jackspeak": {
|
|
||||||
"version": "3.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
|
||||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
|
||||||
"requires": {
|
|
||||||
"@isaacs/cliui": "^8.0.2",
|
|
||||||
"@pkgjs/parseargs": "^0.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"javascript-stringify": {
|
"javascript-stringify": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
|
||||||
@@ -6735,59 +6489,6 @@
|
|||||||
"@sideway/pinpoint": "^2.0.0"
|
"@sideway/pinpoint": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"js-beautify": {
|
|
||||||
"version": "1.15.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
|
|
||||||
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
|
|
||||||
"requires": {
|
|
||||||
"config-chain": "^1.1.13",
|
|
||||||
"editorconfig": "^1.0.4",
|
|
||||||
"glob": "^10.4.2",
|
|
||||||
"js-cookie": "^3.0.5",
|
|
||||||
"nopt": "^7.2.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"glob": {
|
|
||||||
"version": "10.4.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
|
||||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
|
||||||
"requires": {
|
|
||||||
"foreground-child": "^3.1.0",
|
|
||||||
"jackspeak": "^3.1.2",
|
|
||||||
"minimatch": "^9.0.4",
|
|
||||||
"minipass": "^7.1.2",
|
|
||||||
"package-json-from-dist": "^1.0.0",
|
|
||||||
"path-scurry": "^1.11.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "9.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minipass": {
|
|
||||||
"version": "7.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
|
||||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"js-cookie": {
|
|
||||||
"version": "3.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
|
|
||||||
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="
|
|
||||||
},
|
|
||||||
"js-message": {
|
"js-message": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
|
||||||
@@ -7010,16 +6711,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
},
|
},
|
||||||
"lodash-es": {
|
|
||||||
"version": "4.17.21",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
|
||||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
|
||||||
},
|
|
||||||
"lodash.clonedeep": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
|
||||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
|
|
||||||
},
|
|
||||||
"lodash.debounce": {
|
"lodash.debounce": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||||
@@ -7032,11 +6723,6 @@
|
|||||||
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
|
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.isequal": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
|
||||||
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
|
|
||||||
},
|
|
||||||
"lodash.kebabcase": {
|
"lodash.kebabcase": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
|
||||||
@@ -7655,14 +7341,6 @@
|
|||||||
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
|
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"nopt": {
|
|
||||||
"version": "7.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
|
|
||||||
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
|
|
||||||
"requires": {
|
|
||||||
"abbrev": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"normalize-package-data": {
|
"normalize-package-data": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||||
@@ -7983,11 +7661,6 @@
|
|||||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"package-json-from-dist": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
|
|
||||||
},
|
|
||||||
"param-case": {
|
"param-case": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
|
||||||
@@ -7996,11 +7669,6 @@
|
|||||||
"no-case": "^2.2.0"
|
"no-case": "^2.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parchment": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A=="
|
|
||||||
},
|
|
||||||
"parent-module": {
|
"parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -8114,27 +7782,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||||
},
|
},
|
||||||
"path-scurry": {
|
|
||||||
"version": "1.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
|
||||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
|
||||||
"requires": {
|
|
||||||
"lru-cache": "^10.2.0",
|
|
||||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"lru-cache": {
|
|
||||||
"version": "10.4.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
|
||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
|
|
||||||
},
|
|
||||||
"minipass": {
|
|
||||||
"version": "7.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
|
||||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.12",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||||
@@ -8664,11 +8311,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz",
|
||||||
"integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="
|
"integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="
|
||||||
},
|
},
|
||||||
"proto-list": {
|
|
||||||
"version": "1.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
|
||||||
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="
|
|
||||||
},
|
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@@ -8761,34 +8403,6 @@
|
|||||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"quill": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
|
|
||||||
"requires": {
|
|
||||||
"eventemitter3": "^5.0.1",
|
|
||||||
"lodash-es": "^4.17.21",
|
|
||||||
"parchment": "^3.0.0",
|
|
||||||
"quill-delta": "^5.1.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"eventemitter3": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"quill-delta": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
|
|
||||||
"requires": {
|
|
||||||
"fast-diff": "^1.3.0",
|
|
||||||
"lodash.clonedeep": "^4.5.0",
|
|
||||||
"lodash.isequal": "^4.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"randombytes": {
|
"randombytes": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
@@ -9915,6 +9529,7 @@
|
|||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
@@ -9924,37 +9539,14 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
},
|
"dev": true
|
||||||
"strip-ansi": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^5.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-width-cjs": {
|
|
||||||
"version": "npm:string-width@4.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
|
||||||
"requires": {
|
|
||||||
"emoji-regex": "^8.0.0",
|
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
|
||||||
"strip-ansi": "^6.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^5.0.1"
|
"ansi-regex": "^5.0.1"
|
||||||
}
|
}
|
||||||
@@ -9984,21 +9576,6 @@
|
|||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip-ansi-cjs": {
|
|
||||||
"version": "npm:strip-ansi@6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^5.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-eof": {
|
"strip-eof": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||||
@@ -10809,16 +10386,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
|
||||||
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw=="
|
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw=="
|
||||||
},
|
},
|
||||||
"wangeditor": {
|
|
||||||
"version": "4.7.15",
|
|
||||||
"resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.15.tgz",
|
|
||||||
"integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==",
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime": "^7.11.2",
|
|
||||||
"@babel/runtime-corejs3": "^7.11.2",
|
|
||||||
"tslib": "^2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
||||||
@@ -11311,39 +10878,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"wrap-ansi-cjs": {
|
|
||||||
"version": "npm:wrap-ansi@7.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
|
||||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^4.0.0",
|
|
||||||
"string-width": "^4.1.0",
|
|
||||||
"strip-ansi": "^6.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "6.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "^5.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|||||||
@@ -9,22 +9,18 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@stomp/stompjs": "^7.1.1",
|
"@dreysolano/prerender-spa-plugin": "^1.0.3",
|
||||||
"@tinymce/tinymce-vue": "^6.2.0",
|
|
||||||
"amfe-flexible": "^2.2.1",
|
"amfe-flexible": "^2.2.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.5.0",
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"js-beautify": "^1.15.4",
|
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"quill": "^2.0.3",
|
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-i18n": "^8.22.2",
|
"vue-i18n": "^8.22.2",
|
||||||
"vue-meta-info": "^0.1.7",
|
"vue-meta-info": "^0.1.7",
|
||||||
"vue-router": "^3.5.1",
|
"vue-router": "^3.5.1",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2"
|
||||||
"wangeditor": "^4.7.15"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.16",
|
"@babel/core": "^7.12.16",
|
||||||
@@ -34,12 +30,15 @@
|
|||||||
"@vue/cli-plugin-router": "~5.0.0",
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
"@vue/cli-plugin-vuex": "~5.0.0",
|
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||||
"@vue/cli-service": "~5.0.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
|
"compression-webpack-plugin": "^6.1.1",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"less-loader": "^12.2.0",
|
"less-loader": "^12.2.0",
|
||||||
"sass": "^1.79.1",
|
"sass": "^1.79.1",
|
||||||
"sass-loader": "^12.6.0",
|
"sass-loader": "^12.6.0",
|
||||||
"vue-template-compiler": "^2.6.14"
|
"sitemap-webpack-plugin": "^1.1.1",
|
||||||
|
"vue-template-compiler": "^2.6.14",
|
||||||
|
"webpack-merge": "^6.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
<link rel="alternate" hreflang="x-default" href="https://m2pool.com/en">
|
<link rel="alternate" hreflang="x-default" href="https://m2pool.com/en">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Open Graph 标签 - 用于社交媒体分享时的展示效果 -->
|
<!-- Open Graph 标签 - 用于社交媒体分享时的展示效果 -->
|
||||||
<!--分享时显示的标题 -->
|
<!--分享时显示的标题 -->
|
||||||
<meta property="og:title" content="M2pool - Stable leading high-yield mining pool">
|
<meta property="og:title" content="M2pool - Stable leading high-yield mining pool">
|
||||||
@@ -44,10 +45,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css">
|
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_4582735_irzdjxdsrq8.css">
|
||||||
<title>M2pool - Stable leading high-yield mining pool</title>
|
<title>M2pool - Stable leading high-yield mining pool</title>
|
||||||
<meta name="keywords" content="M2Pool, cryptocurrency mining pool,entropyx, bitcoin mining, DGB mining, mining pool service, 加密货币矿池, 比特币挖矿, DGB挖矿">
|
<meta name="keywords" content="M2Pool, cryptocurrency mining pool,Entropyx(enx),entropyx, bitcoin mining, DGB mining, mining pool service, 加密货币矿池, 比特币挖矿, DGB挖矿">
|
||||||
<meta name="description" content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining, including nexa, grs, mona, dgb, rxd">
|
<meta name="description" content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining, including nexa, grs, mona, dgb, rxd, enx">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -2,98 +2,54 @@
|
|||||||
<div id="app">
|
<div id="app">
|
||||||
<router-view class="page" />
|
<router-view class="page" />
|
||||||
|
|
||||||
<ChatWidget v-if="!$route.path.includes('/customerService') && !$isMobile && jurisdiction.roleKey !== 'back_admin'" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script >
|
<script >
|
||||||
import ChatWidget from "../src/components/ChatWidget.vue";
|
import { Debounce, throttle } from '@/utils/publicMethods';
|
||||||
import { Debounce, throttle } from "@/utils/publicMethods";
|
import Vue from 'vue'
|
||||||
import Vue from "vue";
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: 'App',
|
||||||
|
|
||||||
|
|
||||||
components: {
|
|
||||||
ChatWidget,
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
flag: false,
|
flag: false,
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
jurisdiction: {
|
|
||||||
roleKey: "",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
window.addEventListener("resize", Debounce( this.updateWindowWidth,10));
|
window.addEventListener("resize", Debounce( this.updateWindowWidth,10));
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
|
|
||||||
window.addEventListener("setItem", () => {
|
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction
|
|
||||||
? JSON.parse(jurisdiction)
|
|
||||||
: { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
|
|
||||||
window.addEventListener("setItem", () => {
|
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction
|
|
||||||
? JSON.parse(jurisdiction)
|
|
||||||
: { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener("resize", this.updateWindowWidth); // 移除监听器
|
window.removeEventListener("resize", this.updateWindowWidth); // 移除监听器
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
updateWindowWidth(){
|
updateWindowWidth(){
|
||||||
console.log(
|
console.log(window.innerWidth ||
|
||||||
window.innerWidth ||
|
|
||||||
document.documentElement.clientWidth ||
|
document.documentElement.clientWidth ||
|
||||||
document.body.clientWidth
|
document.body.clientWidth)
|
||||||
);
|
|
||||||
//取到了屏幕宽度
|
//取到了屏幕宽度
|
||||||
|
|
||||||
const screenWidth =
|
const screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||||
window.innerWidth ||
|
|
||||||
document.documentElement.clientWidth ||
|
|
||||||
document.body.clientWidth;
|
|
||||||
const isNarrowScreen = screenWidth < 1280;
|
const isNarrowScreen = screenWidth < 1280;
|
||||||
Vue.prototype.$isMobile = isNarrowScreen;
|
Vue.prototype.$isMobile = isNarrowScreen
|
||||||
location.reload();
|
location.reload();
|
||||||
},
|
|
||||||
},
|
}
|
||||||
};
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background-color: #ffffff;
|
--background-color: #ffffff;
|
||||||
--text-color: #000000;
|
--text-color: #000000;
|
||||||
@@ -108,14 +64,16 @@ export default {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
html,
|
html,body{
|
||||||
body {
|
|
||||||
//隐藏滚动条
|
//隐藏滚动条
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#app {
|
#app {
|
||||||
// font-family: Avenir, Helvetica, Arial, sans-serif;
|
// font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
@@ -129,14 +87,16 @@ body {
|
|||||||
/* 滚动条整体部分 */
|
/* 滚动条整体部分 */
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px; /* 宽度 */
|
width: 5PX; /* 宽度 */
|
||||||
height: 6px; /* 高度 */
|
height: 6px; /* 高度 */
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 滚动条滑块 */
|
/* 滚动条滑块 */
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background-color: #d2c3e9; /* 滑块颜色 */
|
background-color: #D2C3E9; /* 滑块颜色 */
|
||||||
border-radius: 20px; /* 圆角 */
|
border-radius: 20PX; /* 圆角 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 滚动条轨道 */
|
/* 滚动条轨道 */
|
||||||
@@ -152,29 +112,15 @@ body {
|
|||||||
input[type="number"] {
|
input[type="number"] {
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-message {
|
|
||||||
//提示信息的层级设置
|
.el-message{ //提示信息的层级设置
|
||||||
|
|
||||||
z-index: 99999 !important;
|
z-index: 99999 !important;
|
||||||
min-width: 300px !important;
|
min-width: 300px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-content {
|
|
||||||
|
|
||||||
:deep(p) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: 2 !important;
|
|
||||||
margin: 0.8em 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
//用于获取m2pool广播数据 主页循环播放
|
|
||||||
export function getBroadcast(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/find/data/by/id`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//新增广播
|
|
||||||
export function getAddBroadcast(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/add`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除广播
|
|
||||||
export function DeleteBroadcast(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/delete`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//分页查询所有广播信息
|
|
||||||
export function listBroadcast(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/get/list/by/page`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//修改广播内容
|
|
||||||
export function updateBroadcast(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/update`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//修改查看通知详情
|
|
||||||
export function dataInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/broadcast/find/data/info`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
//历史聊天记录查询 用户查询七天前的聊天信息
|
|
||||||
export function getHistory(data) {
|
|
||||||
return request({
|
|
||||||
url: `chat/message/find/history/message`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//历史聊天记录查询 查询七天内记录
|
|
||||||
export function getHistory7(data) {
|
|
||||||
return request({
|
|
||||||
url: `chat/message/find/recently/message`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//用户点击对话框默认已读
|
|
||||||
export function getReadMessage(data) {
|
|
||||||
return request({
|
|
||||||
url: `chat/message/read/message`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//聊天列表
|
|
||||||
export function getRoomList(data) {
|
|
||||||
return request({
|
|
||||||
url: `/chat/rooms/find/room/list`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//重要聊天标记
|
|
||||||
export function getUpdateRoom(data) {
|
|
||||||
return request({
|
|
||||||
url: `/chat/rooms/update/room`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//图片上传接口
|
|
||||||
// export function getFileUpdate(data) {
|
|
||||||
// return request({
|
|
||||||
// url: `file/update`,
|
|
||||||
// method: 'post',
|
|
||||||
// data
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
//图根据当前用户邮箱查询聊天室id
|
|
||||||
export function getUserid(data) {
|
|
||||||
return request({
|
|
||||||
url: `chat/rooms/find/room/by/userid`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//上传图片
|
|
||||||
export function getFileUpdate(data) {
|
|
||||||
return request({
|
|
||||||
url: `pool/ticket/uploadFile`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
//查询文档列表 及根据关键搜素接口
|
|
||||||
export function getListDataByPage(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/getListDataByPage`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//新增文档
|
|
||||||
export function addDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/addDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//删除文档
|
|
||||||
export function deleteDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/deleteDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//业务系统获取文档列表
|
|
||||||
export function documentsList(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/findCatalogueDocumentList`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//文档详情
|
|
||||||
export function findDataInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/findDataInfo`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//修改文档
|
|
||||||
export function updateDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/updateDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//待支付汇总
|
|
||||||
export function summaryOfPendingPayments(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/summaryOfPendingPayments`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -84,23 +84,3 @@ export function getUserProfile() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//获取注销账户验证码
|
|
||||||
export function sendCloseAccount(data) {
|
|
||||||
return request({
|
|
||||||
url: `auth/sendCloseAccount`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//注销账户
|
|
||||||
export function closeAccount(data) {
|
|
||||||
return request({
|
|
||||||
url: `auth/closeAccount`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
|
|
||||||
//新增文档页面
|
|
||||||
export function addDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/addDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//业务系统获取对应文档列表
|
|
||||||
export function documentsList(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/findCatalogueDocumentList`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//从列表获取文档详情
|
|
||||||
export function findDataInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/documents/findDataInfo`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
//根据条件 查询注册用户列表
|
|
||||||
export function getUserList(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/list/info`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//发送邮件给用户
|
|
||||||
export function sendMail(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/send/text/mail/message`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//获取单个用户详情
|
|
||||||
export function getUserDetails(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/get/user/info`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//用户详情曲线图
|
|
||||||
export function getUserLineChart(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/getMiningPowerInfo`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//用户离线柱状图
|
|
||||||
export function getUserOnlineStatus(data) {
|
|
||||||
return request({
|
|
||||||
url: `manage/user/getMinerUserOnlineStatus`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 904 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 211.67 211.67"><defs><style>.cls-1{fill:#1c1827;}.cls-2{fill:#c2ff28;}</style></defs><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><circle class="cls-1" cx="105.83" cy="105.83" r="105.83"/><path class="cls-2" d="M37.86,73.57V112l56.22,62.87,79.73-62.64V73.54L94.33,36.75Zm48.8,73.27-35.73-40V85.15l35.73,9.21Zm14,5.46V97.74l52.29,13.47Zm59.26-70.11V98.91l-98-25.23,33-21.53,64.92,30Z"/></g></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 485 B |
@@ -1,40 +0,0 @@
|
|||||||
.dynamic-content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.7;
|
|
||||||
color: #222;
|
|
||||||
// 富文本样式
|
|
||||||
:deep(table) {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(th), :deep(td) {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
:deep(th) {
|
|
||||||
background: #f3f4f6;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
:deep(strong), :deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
:deep(em), :deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
:deep(a) {
|
|
||||||
color: #661FFB !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-container class="back-admin-layout" style="height: 100vh">
|
|
||||||
<!-- 顶部导航栏 -->
|
|
||||||
<el-header height="10vh" class="admin-header">
|
|
||||||
<div class="logo">
|
|
||||||
<img src="@/assets/img/logo.png" alt="logo" class="logo-img" />
|
|
||||||
<div class="logo-title">
|
|
||||||
<div>{{ $t("backendSystem.title") }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="admin-header-right">
|
|
||||||
<el-dropdown>
|
|
||||||
<span
|
|
||||||
class="el-dropdown-link"
|
|
||||||
style="font-size: 0.9rem; color: rgba(0, 0, 0, 1)"
|
|
||||||
>
|
|
||||||
<img style="width: 20px" src="../assets/img/lang.svg" alt="lang" />
|
|
||||||
<i class="el-icon-caret-bottom el-icon--right"></i>
|
|
||||||
</span>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item
|
|
||||||
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
|
|
||||||
@click.native="handelLang(`zh`)"
|
|
||||||
>简体中文</el-dropdown-item
|
|
||||||
>
|
|
||||||
<el-dropdown-item
|
|
||||||
style="font-size: 0.8rem; color: rgba(0, 0, 0, 1)"
|
|
||||||
@click.native="handelLang(`en`)"
|
|
||||||
>English</el-dropdown-item
|
|
||||||
>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-dropdown>
|
|
||||||
<span class="el-dropdown-link"
|
|
||||||
>{{ userEmail }}<i class="el-icon-arrow-down el-icon--right"></i
|
|
||||||
></span>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item @click.native="handelSignOut"
|
|
||||||
index="999999">{{
|
|
||||||
$t("backendSystem.logout")
|
|
||||||
}}</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
|
|
||||||
<el-container>
|
|
||||||
<!-- 侧边栏 -->
|
|
||||||
<comAside></comAside>
|
|
||||||
|
|
||||||
<!-- 主体内容 -->
|
|
||||||
<el-main class="admin-main">
|
|
||||||
|
|
||||||
<router-view v-if="key !== '/zh' && key !== '/en' &&key !== '/zh/login' && key !== '/en/login' && key !== '/zh/register' && key !== '/en/register'" :key="key" />
|
|
||||||
<div v-else style="color: #333;font-size: 16px;text-align: center;line-height: 100vh;">
|
|
||||||
{{ $t("backendSystem.leftNavigation") }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</el-main>
|
|
||||||
</el-container>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getLogout } from "../api/login";
|
|
||||||
export default {
|
|
||||||
computed: {
|
|
||||||
key() {
|
|
||||||
return this.$route.path;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
comAside: () => import("./comAside.vue"),
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
emailOrOrderNo: "",
|
|
||||||
status: "",
|
|
||||||
minAmount: null,
|
|
||||||
maxAmount: null,
|
|
||||||
dateRange: [],
|
|
||||||
},
|
|
||||||
activeTab: "all",
|
|
||||||
tableData: [
|
|
||||||
// 示例数据
|
|
||||||
{
|
|
||||||
index: 1,
|
|
||||||
email: "user@example.com",
|
|
||||||
orderNo: "20230601001",
|
|
||||||
type: "技术支持",
|
|
||||||
machineCode: "K9-001",
|
|
||||||
createTime: "2023-06-01",
|
|
||||||
fault: "无法启动",
|
|
||||||
status: "处理中",
|
|
||||||
amount: 844.01,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
totalAmount: 844.01,
|
|
||||||
userEmail: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let userEmail = localStorage.getItem("userEmail");
|
|
||||||
try {
|
|
||||||
userEmail = userEmail ? JSON.parse(userEmail) : "";
|
|
||||||
} catch (e) {
|
|
||||||
userEmail = "";
|
|
||||||
}
|
|
||||||
this.userEmail = userEmail;
|
|
||||||
|
|
||||||
window.addEventListener("setItem", () => {
|
|
||||||
let userEmail = localStorage.getItem("userEmail");
|
|
||||||
try {
|
|
||||||
userEmail = userEmail ? JSON.parse(userEmail) : "";
|
|
||||||
} catch (e) {
|
|
||||||
userEmail = "";
|
|
||||||
}
|
|
||||||
this.userEmail = userEmail;
|
|
||||||
});
|
|
||||||
|
|
||||||
//网络变化
|
|
||||||
window.addEventListener("online", this.handleNetworkChange);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchSignOut() {
|
|
||||||
const data = await getLogout();
|
|
||||||
if (data && data.code == 200) {
|
|
||||||
|
|
||||||
// 调用 Vuex 的 logout action 清除前端状态
|
|
||||||
await this.$store.dispatch('logout')
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelSignOut() {
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/login`);
|
|
||||||
localStorage.removeItem(`token`);
|
|
||||||
localStorage.removeItem("username");
|
|
||||||
localStorage.removeItem("jurisdiction");
|
|
||||||
this.$addStorageEvent(1, `miningAccountList`, JSON.stringify(""));
|
|
||||||
this.fetchSignOut();
|
|
||||||
|
|
||||||
},
|
|
||||||
handelLang(lang) {
|
|
||||||
try {
|
|
||||||
const currentPath = this.$route.path;
|
|
||||||
const oldLang = this.$i18n.locale;
|
|
||||||
const currentQuery = this.$route.query; // 获取当前的查询参数
|
|
||||||
|
|
||||||
// 检查是否是支持的语言
|
|
||||||
if (!["zh", "en"].includes(lang)) {
|
|
||||||
throw new Error("Unsupported language");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新语言设置
|
|
||||||
this.$i18n.locale = lang;
|
|
||||||
localStorage.setItem("lang", lang || "en");
|
|
||||||
|
|
||||||
// 构造新的路由配置
|
|
||||||
const newPath = currentPath.replace(`/${oldLang}`, `/${lang}`);
|
|
||||||
|
|
||||||
// 保持原有查询参数
|
|
||||||
this.$router
|
|
||||||
.push({
|
|
||||||
path: newPath,
|
|
||||||
query: currentQuery, // 保留原有的查询参数
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (err.name !== "NavigationDuplicated") {
|
|
||||||
console.error("路由更新失败:", err);
|
|
||||||
this.$message.error(this.$t("common.langChangeFailed"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 更新HTML的lang属性
|
|
||||||
document.documentElement.lang = lang;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("语言切换失败:", error);
|
|
||||||
this.$message.error(this.$t("common.langChangeFailed"));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 处理网络状态变化
|
|
||||||
handleNetworkChange() {
|
|
||||||
|
|
||||||
if (navigator.onLine) {
|
|
||||||
// === 强制重置状态,兜底 ===
|
|
||||||
location.reload(); // 重新加载当前页面
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
window.removeEventListener("online", this.handleNetworkChange);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
*{
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.back-admin-layout {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background: #f5f6fa;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.admin-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
height: 15vh;
|
|
||||||
background: #fff;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding: 0 32px;
|
|
||||||
}
|
|
||||||
.logo {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.logo-img {
|
|
||||||
width: 6vw;
|
|
||||||
height: auto;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
.logo-title {
|
|
||||||
font-size: 1vw;
|
|
||||||
font-weight: bold;
|
|
||||||
color: rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
.logo-sub {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
.admin-header-right {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
.lang {
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-left: 16px;
|
|
||||||
}
|
|
||||||
.admin-main {
|
|
||||||
background: #fff;
|
|
||||||
margin: 24px;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 30px;
|
|
||||||
min-width: 0;
|
|
||||||
min-height: 0;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
/* background: palegoldenrod; */
|
|
||||||
height: 84vh ;
|
|
||||||
overflow: hidden;
|
|
||||||
/* overflow-y: auto; */
|
|
||||||
|
|
||||||
}
|
|
||||||
.main-title {
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.main-filters {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------侧边栏----- */
|
|
||||||
</style>
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,724 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="horizontal-broadcast-container" v-if="shouldShowBroadcast">
|
|
||||||
<!-- 广播标题区域 -->
|
|
||||||
<div class="broadcast-header" v-if="showTitle">
|
|
||||||
<i class="iconfont icon-tishishuoming" v-if="showIcon"></i>
|
|
||||||
<span class="broadcast-title">{{ $t('home.describeTitle') }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 横向滚动区域 -->
|
|
||||||
<div
|
|
||||||
class="horizontal-scroll-wrapper"
|
|
||||||
:class="{ 'is-hovering': isHovering, 'full-width': !showTitle }"
|
|
||||||
@mouseenter="stopHorizontalScroll"
|
|
||||||
@mouseleave="resumeHorizontalScroll"
|
|
||||||
@touchstart="stopHorizontalScroll"
|
|
||||||
@touchend="startHorizontalScrollDelayed"
|
|
||||||
:title="isHovering ? $t(`backendSystem.broadcastPause`) || '广播已暂停,移开鼠标继续滚动' : $t(`backendSystem.broadcastResume`) || '鼠标悬停可暂停滚动'"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="horizontal-scroll-content"
|
|
||||||
:style="horizontalScrollStyle"
|
|
||||||
ref="horizontalScrollContent"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in broadcastListForHorizontal"
|
|
||||||
:key="item.id + '-horizontal-' + index"
|
|
||||||
class="horizontal-broadcast-item"
|
|
||||||
@click="handleItemClick(item)"
|
|
||||||
>
|
|
||||||
<span class="horizontal-item-content">{{ item.content }}</span>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 动态渲染多个按钮 -->
|
|
||||||
<div class="button-group" v-if="item.buttonContent && item.buttonContent.length > 0">
|
|
||||||
<span
|
|
||||||
v-for="(buttonText, buttonIndex) in item.buttonContent"
|
|
||||||
:key="`button-${item.id}-${buttonIndex}`"
|
|
||||||
class="view"
|
|
||||||
@click.stop="handelJump(item.buttonPath[buttonIndex])"
|
|
||||||
>
|
|
||||||
{{ buttonText || $t(`home.view`) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="horizontal-item-separator" v-if="index < broadcastListForHorizontal.length - 1">•</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getBroadcast } from '../api/broadcast'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'HorizontalBroadcast',
|
|
||||||
props: {
|
|
||||||
// 广播数据,如果不传则自动获取
|
|
||||||
broadcastData: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
},
|
|
||||||
// 是否显示标题
|
|
||||||
showTitle: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
// 是否显示图标
|
|
||||||
showIcon: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
// 自定义标题
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 滚动速度 (px/step)
|
|
||||||
scrollSpeed: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
// 滚动间隔 (ms)
|
|
||||||
scrollInterval: {
|
|
||||||
type: Number,
|
|
||||||
default: 50
|
|
||||||
},
|
|
||||||
// 是否自动获取数据
|
|
||||||
autoFetch: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
// 获取数据的语言参数
|
|
||||||
lang: {
|
|
||||||
type: String,
|
|
||||||
default: 'zh'
|
|
||||||
},
|
|
||||||
// 最小显示条数(少于此数不显示组件)
|
|
||||||
minItems: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
// 组件高度
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: '40px'
|
|
||||||
},
|
|
||||||
// 是否启用点击事件
|
|
||||||
clickable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
// 内部广播数据
|
|
||||||
internalBroadcastList: [],
|
|
||||||
// 横向滚动相关
|
|
||||||
horizontalScrollTimer: null,
|
|
||||||
horizontalDelayTimer: null,
|
|
||||||
horizontalScrollOffset: 0,
|
|
||||||
isHorizontalScrolling: true,
|
|
||||||
// hover状态控制
|
|
||||||
isHovering: false,
|
|
||||||
wasScrollingBeforeHover: true,
|
|
||||||
// 组件状态
|
|
||||||
isLoading: false,
|
|
||||||
hasError: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// 最终使用的广播数据
|
|
||||||
finalBroadcastList() {
|
|
||||||
let sourceData = this.broadcastData.length > 0
|
|
||||||
? this.broadcastData
|
|
||||||
: this.internalBroadcastList;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 统一处理数据格式转换
|
|
||||||
const processedData = sourceData.map(item => {
|
|
||||||
const processedItem = { ...item };
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 处理 buttonContent:如果是字符串则分割为数组
|
|
||||||
if (typeof processedItem.buttonContent === 'string' && processedItem.buttonContent.trim()) {
|
|
||||||
processedItem.buttonContent = processedItem.buttonContent
|
|
||||||
.split(/[,,]\s*/) // 支持中英文逗号,后面可能跟空格
|
|
||||||
.map(btn => btn.trim())
|
|
||||||
.filter(btn => btn); // 过滤空字符串
|
|
||||||
} else if (!Array.isArray(processedItem.buttonContent)) {
|
|
||||||
processedItem.buttonContent = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 buttonPath:如果是字符串则分割为数组
|
|
||||||
if (typeof processedItem.buttonPath === 'string' && processedItem.buttonPath.trim()) {
|
|
||||||
processedItem.buttonPath = processedItem.buttonPath
|
|
||||||
.split(/[,,]\s*/) // 支持中英文逗号,后面可能跟空格
|
|
||||||
.map(path => path.trim())
|
|
||||||
.filter(path => path); // 过滤空字符串
|
|
||||||
} else if (!Array.isArray(processedItem.buttonPath)) {
|
|
||||||
processedItem.buttonPath = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只有当两个数组都有内容时才进行长度校验
|
|
||||||
if (processedItem.buttonContent.length > 0 && processedItem.buttonPath.length > 0) {
|
|
||||||
// 确保两个数组长度一致,以较短的为准
|
|
||||||
const minLength = Math.min(
|
|
||||||
processedItem.buttonContent.length,
|
|
||||||
processedItem.buttonPath.length
|
|
||||||
);
|
|
||||||
|
|
||||||
processedItem.buttonContent = processedItem.buttonContent.slice(0, minLength);
|
|
||||||
processedItem.buttonPath = processedItem.buttonPath.slice(0, minLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return processedItem;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return processedData;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 是否应该显示广播组件
|
|
||||||
shouldShowBroadcast() {
|
|
||||||
return this.finalBroadcastList.length >= this.minItems && !this.hasError;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 横向滚动用的数据(复制数据实现无缝循环)
|
|
||||||
broadcastListForHorizontal() {
|
|
||||||
const list = this.finalBroadcastList;
|
|
||||||
|
|
||||||
|
|
||||||
if (list.length === 0) return [];
|
|
||||||
|
|
||||||
let result;
|
|
||||||
if (list.length === 1) {
|
|
||||||
// 单条数据时复制多次以实现连续滚动
|
|
||||||
result = Array(3).fill().map((_, idx) => ({
|
|
||||||
...list[0],
|
|
||||||
id: list[0].id + '-copy-' + idx
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
// 多条数据时在末尾添加第一条实现无缝循环
|
|
||||||
result = [...list, list[0]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 横向滚动样式
|
|
||||||
horizontalScrollStyle() {
|
|
||||||
return {
|
|
||||||
transform: `translateX(-${this.horizontalScrollOffset}px)`,
|
|
||||||
transition: this.isHorizontalScrolling ? 'none' : 'transform 0.3s ease',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
// 监听外部数据变化
|
|
||||||
broadcastData: {
|
|
||||||
handler(newData) {
|
|
||||||
if (newData && newData.length > 0) {
|
|
||||||
this.resetScroll();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
immediate: true
|
|
||||||
},
|
|
||||||
// 监听滚动参数变化
|
|
||||||
scrollSpeed(newSpeed) {
|
|
||||||
this.horizontalScrollSpeed = newSpeed;
|
|
||||||
},
|
|
||||||
scrollInterval(newInterval) {
|
|
||||||
this.horizontalScrollInterval = newInterval;
|
|
||||||
if (this.isHorizontalScrolling) {
|
|
||||||
this.restartScroll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
|
|
||||||
|
|
||||||
// 如果没有外部数据且允许自动获取,则获取数据
|
|
||||||
if (this.autoFetch && this.broadcastData.length === 0) {
|
|
||||||
this.fetchBroadcastData();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动滚动
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.startHorizontalScroll();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 获取广播数据
|
|
||||||
*/
|
|
||||||
async fetchBroadcastData() {
|
|
||||||
if (this.isLoading) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.hasError = false;
|
|
||||||
|
|
||||||
const data = await getBroadcast({ lang: this.lang || (this.$i18n ? this.$i18n.locale : 'zh') });
|
|
||||||
|
|
||||||
if (data && data.code === 200 && Array.isArray(data.data)) {
|
|
||||||
this.internalBroadcastList = data.data;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.resetScroll();
|
|
||||||
this.$emit('data-loaded', data.data);
|
|
||||||
} else {
|
|
||||||
this.hasError = true;
|
|
||||||
this.$emit('error', '获取广播数据失败');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取广播数据失败:', error);
|
|
||||||
this.hasError = true;
|
|
||||||
this.$emit('error', error);
|
|
||||||
} finally {
|
|
||||||
this.isLoading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始横向滚动
|
|
||||||
*/
|
|
||||||
startHorizontalScroll() {
|
|
||||||
// 如果正在hover或数据不足,不启动滚动
|
|
||||||
if (this.isHovering || this.finalBroadcastList.length <= 1) return;
|
|
||||||
|
|
||||||
if (this.horizontalScrollTimer) {
|
|
||||||
clearInterval(this.horizontalScrollTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isHorizontalScrolling = true;
|
|
||||||
this.horizontalScrollTimer = setInterval(() => {
|
|
||||||
this.horizontalScrollStep();
|
|
||||||
}, this.scrollInterval);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止横向滚动
|
|
||||||
*/
|
|
||||||
stopHorizontalScroll() {
|
|
||||||
this.wasScrollingBeforeHover = this.isHorizontalScrolling;
|
|
||||||
this.isHovering = true;
|
|
||||||
|
|
||||||
if (this.horizontalScrollTimer) {
|
|
||||||
clearInterval(this.horizontalScrollTimer);
|
|
||||||
this.horizontalScrollTimer = null;
|
|
||||||
}
|
|
||||||
this.isHorizontalScrolling = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 鼠标移开时恢复滚动
|
|
||||||
*/
|
|
||||||
resumeHorizontalScroll() {
|
|
||||||
this.isHovering = false;
|
|
||||||
|
|
||||||
if (this.wasScrollingBeforeHover && this.finalBroadcastList.length > 1) {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.isHovering) {
|
|
||||||
this.startHorizontalScroll();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelJump(url) {
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理单个路径跳转
|
|
||||||
* @param {string} path - 路径
|
|
||||||
*/
|
|
||||||
const handleSinglePath = (path) => {
|
|
||||||
if (!path || typeof path !== 'string') {
|
|
||||||
console.warn('无效的路径:', path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清理路径
|
|
||||||
const cleanPath = path.trim();
|
|
||||||
if (!cleanPath) {
|
|
||||||
console.warn('路径为空');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let targetPath;
|
|
||||||
|
|
||||||
// 如果是主页路径
|
|
||||||
if (cleanPath === '/' || cleanPath === '') {
|
|
||||||
targetPath = `/${lang}/`;
|
|
||||||
} else {
|
|
||||||
// 其他路径:去掉开头的斜杠(如果有的话)
|
|
||||||
const pathWithoutSlash = cleanPath.startsWith('/') ? cleanPath.substring(1) : cleanPath;
|
|
||||||
targetPath = `/${lang}/${pathWithoutSlash}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('跳转路径:', targetPath);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 在当前页面跳转
|
|
||||||
this.$router.push(targetPath);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('路由跳转失败:', error);
|
|
||||||
// 如果路由跳转失败,尝试直接跳转
|
|
||||||
window.location.href = targetPath;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理传入的路径
|
|
||||||
if (url) {
|
|
||||||
handleSinglePath(url);
|
|
||||||
} else {
|
|
||||||
console.warn('未提供跳转路径');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 延迟启动横向滚动(移动端触摸后)
|
|
||||||
*/
|
|
||||||
startHorizontalScrollDelayed() {
|
|
||||||
if (this.horizontalDelayTimer) {
|
|
||||||
clearTimeout(this.horizontalDelayTimer);
|
|
||||||
}
|
|
||||||
this.horizontalDelayTimer = setTimeout(() => {
|
|
||||||
this.resumeHorizontalScroll();
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 横向滚动步进
|
|
||||||
*/
|
|
||||||
horizontalScrollStep() {
|
|
||||||
if (!this.$refs.horizontalScrollContent) return;
|
|
||||||
|
|
||||||
const contentElement = this.$refs.horizontalScrollContent;
|
|
||||||
const contentWidth = contentElement.scrollWidth;
|
|
||||||
|
|
||||||
// 计算单个循环的宽度
|
|
||||||
const singleCycleWidth = contentWidth / this.broadcastListForHorizontal.length * this.finalBroadcastList.length;
|
|
||||||
|
|
||||||
this.horizontalScrollOffset += this.scrollSpeed;
|
|
||||||
|
|
||||||
// 当滚动超过单个循环宽度时,重置到开始位置实现无缝循环
|
|
||||||
if (this.horizontalScrollOffset >= singleCycleWidth) {
|
|
||||||
this.horizontalScrollOffset = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置滚动
|
|
||||||
*/
|
|
||||||
resetScroll() {
|
|
||||||
this.horizontalScrollOffset = 0;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.finalBroadcastList.length > 1) {
|
|
||||||
this.startHorizontalScroll();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重启滚动
|
|
||||||
*/
|
|
||||||
restartScroll() {
|
|
||||||
this.stopHorizontalScroll();
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.startHorizontalScroll();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 广播项点击事件
|
|
||||||
*/
|
|
||||||
handleItemClick(item) {
|
|
||||||
if (this.clickable) {
|
|
||||||
this.$emit('item-click', item);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手动刷新数据
|
|
||||||
*/
|
|
||||||
refresh() {
|
|
||||||
if (this.autoFetch) {
|
|
||||||
this.fetchBroadcastData();
|
|
||||||
} else {
|
|
||||||
this.resetScroll();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 暂停/继续滚动
|
|
||||||
*/
|
|
||||||
togglePause() {
|
|
||||||
if (this.isHorizontalScrolling) {
|
|
||||||
this.stopHorizontalScroll();
|
|
||||||
} else {
|
|
||||||
this.resumeHorizontalScroll();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取组件状态
|
|
||||||
*/
|
|
||||||
getStatus() {
|
|
||||||
return {
|
|
||||||
isScrolling: this.isHorizontalScrolling,
|
|
||||||
isHovering: this.isHovering,
|
|
||||||
currentOffset: this.horizontalScrollOffset,
|
|
||||||
dataCount: this.finalBroadcastList.length,
|
|
||||||
isLoading: this.isLoading,
|
|
||||||
hasError: this.hasError
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
// 清理定时器
|
|
||||||
if (this.horizontalScrollTimer) {
|
|
||||||
clearInterval(this.horizontalScrollTimer);
|
|
||||||
}
|
|
||||||
if (this.horizontalDelayTimer) {
|
|
||||||
clearTimeout(this.horizontalDelayTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置状态
|
|
||||||
this.isHovering = false;
|
|
||||||
this.isHorizontalScrolling = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
/* 横向滚动广播容器 */
|
|
||||||
.horizontal-broadcast-container {
|
|
||||||
width: 100%;
|
|
||||||
background: #fff;
|
|
||||||
|
|
||||||
// box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0px 20px !important;
|
|
||||||
position: relative;
|
|
||||||
z-index: 100;
|
|
||||||
|
|
||||||
background: #E7DFF3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 广播标题区域 */
|
|
||||||
.broadcast-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-right: 15px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #5721e4;
|
|
||||||
font-size: 18px;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.broadcast-title {
|
|
||||||
color: #5721e4;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 14px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 横向滚动包装器 */
|
|
||||||
.horizontal-scroll-wrapper {
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
height: v-bind(height);
|
|
||||||
// background: #f8f9fa;
|
|
||||||
border-radius: 8px;
|
|
||||||
// border: 1px solid #e9ecef;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&.full-width {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 横向滚动内容 */
|
|
||||||
.horizontal-scroll-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
white-space: nowrap;
|
|
||||||
will-change: transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 横向广播项 */
|
|
||||||
.horizontal-broadcast-item {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
margin-right: 30px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
|
|
||||||
.horizontal-item-content {
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.4;
|
|
||||||
padding: 0 15px;
|
|
||||||
white-space: nowrap;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
|
|
||||||
// &:hover {
|
|
||||||
// color: #5721e4;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮组样式 */
|
|
||||||
.button-group {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
// margin-left: 10px;
|
|
||||||
gap: 0px; /* 按钮之间的间距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-item-separator {
|
|
||||||
color: #ccc;
|
|
||||||
margin: 0 15px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滚动暂停时的视觉反馈 */
|
|
||||||
.horizontal-scroll-wrapper:hover,
|
|
||||||
.horizontal-scroll-wrapper.is-hovering {
|
|
||||||
// background: linear-gradient(135deg, #f0f3ff, #e8f2ff);
|
|
||||||
border-color: #5721e4;
|
|
||||||
// box-shadow: 0 2px 8px rgba(87, 33, 228, 0.15);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* hover状态下的内容样式 */
|
|
||||||
.horizontal-scroll-wrapper.is-hovering .horizontal-item-content {
|
|
||||||
// color: #5721e4;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 暂停指示器圆点 */
|
|
||||||
.horizontal-scroll-wrapper.is-hovering::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 8px;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
background: #5721e4;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: pausePulse 1.5s ease-in-out infinite;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.view{
|
|
||||||
color: #5721e4;
|
|
||||||
// font-size: 0.85rem;
|
|
||||||
// margin-left: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 2px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
white-space: nowrap;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #5721e4;
|
|
||||||
color: #fff;
|
|
||||||
border-color: #5721e4;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pausePulse {
|
|
||||||
0%, 100% {
|
|
||||||
opacity: 0.6;
|
|
||||||
transform: translateY(-50%) scale(1);
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(-50%) scale(1.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media screen and (max-width: 768px) {
|
|
||||||
.horizontal-broadcast-container {
|
|
||||||
padding: 8px 15px;
|
|
||||||
|
|
||||||
.broadcast-header {
|
|
||||||
margin-right: 10px;
|
|
||||||
|
|
||||||
i {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.broadcast-title {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-broadcast-item {
|
|
||||||
margin-right: 20px;
|
|
||||||
|
|
||||||
.horizontal-item-content {
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端按钮组样式 */
|
|
||||||
.button-group {
|
|
||||||
margin-left: 5px;
|
|
||||||
gap: 5px;
|
|
||||||
|
|
||||||
.view {
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 1px 6px;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-item-separator {
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-scroll-wrapper.is-hovering::before {
|
|
||||||
right: 5px;
|
|
||||||
width: 4px;
|
|
||||||
height: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 美化滚动条 */
|
|
||||||
.horizontal-scroll-wrapper::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="password-strength-indicator">
|
|
||||||
<!-- 密码强度进度条 -->
|
|
||||||
<div class="strength-bar-container">
|
|
||||||
<div
|
|
||||||
class="strength-bar"
|
|
||||||
:class="strengthClass"
|
|
||||||
:style="{ width: strengthPercentage + '%' }"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 强度文本提示 -->
|
|
||||||
<div class="strength-text" :class="strengthClass">
|
|
||||||
<span v-if="password && password.length > 0">
|
|
||||||
{{ $t(`passwordStrength.${strengthLevel}`) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 详细的校验项列表 -->
|
|
||||||
<div v-if="showDetails && password && password.length > 0" class="validation-checklist">
|
|
||||||
<div
|
|
||||||
v-for="(rule, key) in validationDetails"
|
|
||||||
:key="key"
|
|
||||||
class="validation-item"
|
|
||||||
:class="{ 'valid': rule.passed, 'invalid': !rule.passed }"
|
|
||||||
>
|
|
||||||
<i :class="rule.passed ? 'el-icon-circle-check' : 'el-icon-circle-close'"></i>
|
|
||||||
<span>{{ $t(rule.message) }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { checkPasswordStrength } from '@/utils/passwordValidator'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PasswordStrengthIndicator',
|
|
||||||
props: {
|
|
||||||
// 要校验的密码
|
|
||||||
password: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 是否显示详细的校验项
|
|
||||||
showDetails: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// 密码强度分析结果
|
|
||||||
strengthAnalysis() {
|
|
||||||
if (!this.password) {
|
|
||||||
return {
|
|
||||||
score: 0,
|
|
||||||
level: 'none',
|
|
||||||
validation: {
|
|
||||||
valid: false,
|
|
||||||
errors: [],
|
|
||||||
details: {
|
|
||||||
length: false,
|
|
||||||
hasLowercase: false,
|
|
||||||
hasUppercase: false,
|
|
||||||
hasNumber: false,
|
|
||||||
hasSpecialChar: false,
|
|
||||||
noChinese: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return checkPasswordStrength(this.password)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 强度等级
|
|
||||||
strengthLevel() {
|
|
||||||
return this.strengthAnalysis.level
|
|
||||||
},
|
|
||||||
|
|
||||||
// 强度百分比
|
|
||||||
strengthPercentage() {
|
|
||||||
return this.strengthAnalysis.score
|
|
||||||
},
|
|
||||||
|
|
||||||
// 强度等级对应的样式类
|
|
||||||
strengthClass() {
|
|
||||||
return `strength-${this.strengthLevel}`
|
|
||||||
},
|
|
||||||
|
|
||||||
// 校验详情(用于显示✓和✗)
|
|
||||||
validationDetails() {
|
|
||||||
const details = this.strengthAnalysis.validation.details
|
|
||||||
return {
|
|
||||||
length: {
|
|
||||||
passed: details.length,
|
|
||||||
message: 'passwordRules.length'
|
|
||||||
},
|
|
||||||
noChinese: {
|
|
||||||
passed: details.noChinese,
|
|
||||||
message: 'passwordRules.noChinese'
|
|
||||||
},
|
|
||||||
lowercase: {
|
|
||||||
passed: details.hasLowercase,
|
|
||||||
message: 'passwordRules.lowercase'
|
|
||||||
},
|
|
||||||
uppercase: {
|
|
||||||
passed: details.hasUppercase,
|
|
||||||
message: 'passwordRules.uppercase'
|
|
||||||
},
|
|
||||||
number: {
|
|
||||||
passed: details.hasNumber,
|
|
||||||
message: 'passwordRules.number'
|
|
||||||
},
|
|
||||||
specialChar: {
|
|
||||||
passed: details.hasSpecialChar,
|
|
||||||
message: 'passwordRules.specialChar'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
// 密码变化时通知父组件校验结果
|
|
||||||
strengthAnalysis: {
|
|
||||||
handler(newVal) {
|
|
||||||
this.$emit('strength-change', newVal)
|
|
||||||
},
|
|
||||||
deep: true,
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.password-strength-indicator {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 强度进度条容器
|
|
||||||
.strength-bar-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 6px;
|
|
||||||
background-color: #e4e7ed;
|
|
||||||
border-radius: 3px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 强度进度条
|
|
||||||
.strength-bar {
|
|
||||||
height: 100%;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
&.strength-weak {
|
|
||||||
background-color: #f56c6c; // 红色 - 弱
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-medium {
|
|
||||||
background-color: #e6a23c; // 橙色 - 中等
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-strong {
|
|
||||||
background-color: #67c23a; // 绿色 - 强
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-none {
|
|
||||||
background-color: #e4e7ed; // 灰色 - 无
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 强度文本
|
|
||||||
.strength-text {
|
|
||||||
font-size: 12px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.strength-weak {
|
|
||||||
color: #f56c6c;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-medium {
|
|
||||||
color: #e6a23c;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-strong {
|
|
||||||
color: #67c23a;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.strength-none {
|
|
||||||
color: #909399;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验项列表
|
|
||||||
.validation-checklist {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.validation-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
|
|
||||||
i {
|
|
||||||
margin-right: 6px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.valid {
|
|
||||||
color: #67c23a;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #67c23a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.invalid {
|
|
||||||
color: #909399;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #dcdfe6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,293 +0,0 @@
|
|||||||
# HorizontalBroadcast 横向滚动广播组件
|
|
||||||
|
|
||||||
一个功能完整的横向滚动广播通知栏组件,支持自动获取数据、鼠标交互、触摸交互等特性。
|
|
||||||
|
|
||||||
## 🚀 快速开始
|
|
||||||
|
|
||||||
### 基础用法
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<!-- 最简单的用法,自动获取数据 -->
|
|
||||||
<HorizontalBroadcast />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import HorizontalBroadcast from '@/components/HorizontalBroadcast.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
HorizontalBroadcast
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📋 Props 属性
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 说明 |
|
|
||||||
|--------|------|--------|------|
|
|
||||||
| `broadcastData` | Array | `[]` | 广播数据,如果不传则自动获取 |
|
|
||||||
| `showTitle` | Boolean | `true` | 是否显示标题 |
|
|
||||||
| `showIcon` | Boolean | `true` | 是否显示图标 |
|
|
||||||
| `title` | String | `''` | 自定义标题,不传则使用国际化标题 |
|
|
||||||
| `scrollSpeed` | Number | `1` | 滚动速度(像素/步) |
|
|
||||||
| `scrollInterval` | Number | `50` | 滚动间隔(毫秒) |
|
|
||||||
| `autoFetch` | Boolean | `true` | 是否自动获取数据 |
|
|
||||||
| `lang` | String | `'zh'` | 获取数据的语言参数 |
|
|
||||||
| `minItems` | Number | `1` | 最小显示条数,少于此数不显示组件 |
|
|
||||||
| `height` | String | `'40px'` | 组件高度 |
|
|
||||||
| `clickable` | Boolean | `false` | 是否启用点击事件 |
|
|
||||||
|
|
||||||
## 📡 Events 事件
|
|
||||||
|
|
||||||
| 事件名 | 参数 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| `data-loaded` | `data: Array` | 数据加载完成时触发 |
|
|
||||||
| `error` | `error: Error` | 发生错误时触发 |
|
|
||||||
| `item-click` | `item: Object` | 广播项被点击时触发(需要 `clickable=true`) |
|
|
||||||
|
|
||||||
## 🎯 使用示例
|
|
||||||
|
|
||||||
### 1. 自定义样式和行为
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<HorizontalBroadcast
|
|
||||||
:show-title="true"
|
|
||||||
:show-icon="true"
|
|
||||||
title="最新公告"
|
|
||||||
height="50px"
|
|
||||||
:scroll-speed="2"
|
|
||||||
:scroll-interval="30"
|
|
||||||
:clickable="true"
|
|
||||||
@item-click="handleClick"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
handleClick(item) {
|
|
||||||
console.log('点击了:', item.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 使用外部数据
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<HorizontalBroadcast
|
|
||||||
:broadcast-data="customData"
|
|
||||||
:auto-fetch="false"
|
|
||||||
title="自定义消息"
|
|
||||||
:clickable="true"
|
|
||||||
@item-click="handleCustomClick"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
customData: [
|
|
||||||
{ id: '1', content: '第一条消息' },
|
|
||||||
{ id: '2', content: '第二条消息' },
|
|
||||||
{ id: '3', content: '第三条消息' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleCustomClick(item) {
|
|
||||||
this.$message.info(item.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 极简模式(无标题无图标)
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<HorizontalBroadcast
|
|
||||||
:show-title="false"
|
|
||||||
:show-icon="false"
|
|
||||||
height="35px"
|
|
||||||
:scroll-speed="1.5"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 错误处理
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<HorizontalBroadcast
|
|
||||||
@data-loaded="onDataLoaded"
|
|
||||||
@error="onError"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
onDataLoaded(data) {
|
|
||||||
console.log('广播数据加载成功:', data);
|
|
||||||
},
|
|
||||||
onError(error) {
|
|
||||||
console.error('广播组件出错:', error);
|
|
||||||
this.$message.error('加载广播数据失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎮 组件方法
|
|
||||||
|
|
||||||
通过 `ref` 访问组件实例,可以调用以下方法:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<HorizontalBroadcast ref="broadcast" />
|
|
||||||
<button @click="refreshData">刷新数据</button>
|
|
||||||
<button @click="togglePause">暂停/继续</button>
|
|
||||||
<button @click="getStatus">获取状态</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
// 刷新数据
|
|
||||||
refreshData() {
|
|
||||||
this.$refs.broadcast.refresh();
|
|
||||||
},
|
|
||||||
|
|
||||||
// 切换暂停状态
|
|
||||||
togglePause() {
|
|
||||||
this.$refs.broadcast.togglePause();
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取组件状态
|
|
||||||
getStatus() {
|
|
||||||
const status = this.$refs.broadcast.getStatus();
|
|
||||||
console.log('组件状态:', status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 可用方法:
|
|
||||||
|
|
||||||
- `refresh()` - 刷新数据
|
|
||||||
- `togglePause()` - 切换暂停/继续状态
|
|
||||||
- `getStatus()` - 获取当前状态信息
|
|
||||||
|
|
||||||
## 🎨 样式定制
|
|
||||||
|
|
||||||
组件使用 scoped 样式,如需定制外观,可以通过以下方式:
|
|
||||||
|
|
||||||
### 1. 通过 Props 定制
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<HorizontalBroadcast
|
|
||||||
height="60px" <!-- 调整高度 -->
|
|
||||||
title="自定义标题" <!-- 自定义标题 -->
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 全局样式覆盖
|
|
||||||
|
|
||||||
```scss
|
|
||||||
// 在全局样式中
|
|
||||||
.horizontal-broadcast-container {
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
|
|
||||||
.broadcast-title {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.horizontal-scroll-wrapper {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📱 移动端适配
|
|
||||||
|
|
||||||
组件已内置移动端适配:
|
|
||||||
|
|
||||||
- 自动调整字体大小和间距
|
|
||||||
- 支持触摸交互(触摸暂停,松开恢复)
|
|
||||||
- 响应式布局自适应
|
|
||||||
|
|
||||||
## 🔧 数据格式
|
|
||||||
|
|
||||||
广播数据应遵循以下格式:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
[
|
|
||||||
{
|
|
||||||
id: 'unique-id-1', // 必需:唯一标识
|
|
||||||
content: '广播内容...' // 必需:显示内容
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'unique-id-2',
|
|
||||||
content: '另一条广播内容...'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🌐 国际化支持
|
|
||||||
|
|
||||||
组件支持国际化,默认标题会使用 `this.$t('home.describeTitle')`。
|
|
||||||
|
|
||||||
如需自定义,可以:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<HorizontalBroadcast
|
|
||||||
:title="$t('custom.broadcast.title')"
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚡ 性能优化
|
|
||||||
|
|
||||||
组件已内置以下性能优化:
|
|
||||||
|
|
||||||
- 使用 `will-change: transform` 启用硬件加速
|
|
||||||
- 智能的数据复制策略减少 DOM 操作
|
|
||||||
- 自动清理定时器防止内存泄漏
|
|
||||||
- 合理的滚动间隔和步进设置
|
|
||||||
|
|
||||||
## 🐛 常见问题
|
|
||||||
|
|
||||||
### Q: 为什么组件没有显示?
|
|
||||||
|
|
||||||
A: 检查以下几点:
|
|
||||||
1. 数据是否正确加载(通过 `@data-loaded` 事件检查)
|
|
||||||
2. `minItems` 设置是否过高
|
|
||||||
3. 是否有 CSS 冲突
|
|
||||||
|
|
||||||
### Q: 如何调整滚动速度?
|
|
||||||
|
|
||||||
A: 通过 `scrollSpeed` 和 `scrollInterval` 两个属性:
|
|
||||||
- `scrollSpeed`: 每次移动的像素数(越大越快)
|
|
||||||
- `scrollInterval`: 滚动间隔毫秒数(越小越快)
|
|
||||||
|
|
||||||
### Q: 点击事件不生效?
|
|
||||||
|
|
||||||
A: 确保设置了 `clickable="true"` 并监听 `@item-click` 事件。
|
|
||||||
|
|
||||||
## <20><> 许可证
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,163 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-aside
|
|
||||||
style="height: 100vh; background: #202940; width: 280px; padding: 0"
|
|
||||||
class="admin-sidebar"
|
|
||||||
>
|
|
||||||
<el-menu
|
|
||||||
style="border: none; width: 280px"
|
|
||||||
:default-active="activeIndex"
|
|
||||||
class="el-menu-vertical-demo"
|
|
||||||
background-color="#202940"
|
|
||||||
text-color="#fff"
|
|
||||||
active-text-color="#ffd04b"
|
|
||||||
>
|
|
||||||
<div v-for="item in menuList" :key="item.id">
|
|
||||||
<el-menu-item
|
|
||||||
@click="handleClick(item)"
|
|
||||||
v-show="!item.children"
|
|
||||||
:index="item.id"
|
|
||||||
style="padding-left: 20px !important"
|
|
||||||
>
|
|
||||||
<i :class="item.icon"></i>
|
|
||||||
<span slot="title">{{ $t(item.label) }}</span>
|
|
||||||
</el-menu-item>
|
|
||||||
|
|
||||||
<el-submenu id="el-submenu-bg" :index="item.id" v-if="item.children">
|
|
||||||
<template slot="title">
|
|
||||||
<i :class="item.icon"></i>
|
|
||||||
<span>{{ $t(item.label) }}</span>
|
|
||||||
</template>
|
|
||||||
<el-menu-item
|
|
||||||
@click="handleClick(child)"
|
|
||||||
v-for="child in item.children"
|
|
||||||
:key="child.id"
|
|
||||||
:index="child.id"
|
|
||||||
style="padding-left: 40px !important"
|
|
||||||
>
|
|
||||||
<i :class="child.icon"></i>
|
|
||||||
<span slot="title">{{ $t(child.label) }}</span>
|
|
||||||
</el-menu-item>
|
|
||||||
</el-submenu>
|
|
||||||
</div>
|
|
||||||
</el-menu>
|
|
||||||
</el-aside>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
menuList: [
|
|
||||||
// {
|
|
||||||
// //广播
|
|
||||||
// path: "broadcast",
|
|
||||||
// label: `backendSystem.broadcast`,
|
|
||||||
// icon: "el-icon-bell",
|
|
||||||
// id: "1",
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
//用户管理
|
|
||||||
// path: "userManagement",
|
|
||||||
label: `backendSystem.userRelated`,
|
|
||||||
icon: "el-icon-user",
|
|
||||||
id: "2",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
//用户管理
|
|
||||||
path: "userManagement",
|
|
||||||
label: `backendSystem.userManagement`,
|
|
||||||
icon: "el-icon-user",
|
|
||||||
id: "2-1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
//待支付汇总
|
|
||||||
path: "pendingPaymentSummary",
|
|
||||||
label: `backendSystem.pendingPaymentSummary`,
|
|
||||||
icon: "el-icon-wallet",
|
|
||||||
id: "2-2",
|
|
||||||
},
|
|
||||||
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
//工单管理
|
|
||||||
path: "workOrderBackend",
|
|
||||||
label: `backendSystem.workOrder`,
|
|
||||||
icon: "el-icon-document-copy",
|
|
||||||
id: "3",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
//文档管理
|
|
||||||
path: "documentManagement",
|
|
||||||
label: `backendSystem.documentManagement`,
|
|
||||||
icon: "el-icon-folder-opened",
|
|
||||||
id: "4",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
//广播
|
|
||||||
path: "broadcast",
|
|
||||||
label: `backendSystem.broadcast`,
|
|
||||||
icon: "el-icon-bell",
|
|
||||||
id: "4-1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
//发布文章
|
|
||||||
path: "documentManagement",
|
|
||||||
label: `backendSystem.publishArticle`,
|
|
||||||
icon: "el-icon-edit-outline",
|
|
||||||
id: "4-2",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
activeIndex: "0",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
const currentPath = this.$route.path.replace(`/${lang}/`, "");
|
|
||||||
// 优先根据当前路由匹配菜单项
|
|
||||||
const matchedMenu = this.menuList.find((item) => item.path === currentPath);
|
|
||||||
console.log(matchedMenu, "matchedMenu");
|
|
||||||
if (matchedMenu) {
|
|
||||||
this.activeIndex = matchedMenu.id;
|
|
||||||
this.$addStorageEvent(1, "activeIndex", matchedMenu.id);
|
|
||||||
} else {
|
|
||||||
// 如果localStorage有值,优先用localStorage
|
|
||||||
const savedIndex = localStorage.getItem("activeIndex");
|
|
||||||
if (savedIndex) {
|
|
||||||
this.activeIndex = savedIndex;
|
|
||||||
} else {
|
|
||||||
this.$addStorageEvent(1, "activeIndex", this.activeIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (this.activeIndex == "0") {
|
|
||||||
this.activeIndex = "2-1";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleClick(item) {
|
|
||||||
console.log(item, "item");
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/${item.path}`);
|
|
||||||
this.activeIndex = item.id;
|
|
||||||
this.$addStorageEvent(1, "activeIndex", item.id);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
localStorage.removeItem("activeIndex");
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.el-submenu .el-menu-item {
|
|
||||||
padding-left: 40px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<!-- <li>{{ $t(`home.historicalAnnouncement`) }}</li>
|
<!-- <li>{{ $t(`home.historicalAnnouncement`) }}</li>
|
||||||
<li>{{ $t(`home.commonProblem`) }}</li> -->
|
<li>{{ $t(`home.commonProblem`) }}</li> -->
|
||||||
<li > <span @click="jumpPage4(`/submitWorkOrder`)">{{ $t(`home.submitWorkOrder`) }}</span></li>
|
<li > <span @click="jumpPage3(`/submitWorkOrder`)">{{ $t(`home.submitWorkOrder`) }}</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -292,36 +292,27 @@ export default {
|
|||||||
const coin = this.currencyList.find(item => item.value === this.activeItemCoin.value);
|
const coin = this.currencyList.find(item => item.value === this.activeItemCoin.value);
|
||||||
if (!coin) return;
|
if (!coin) return;
|
||||||
let jumpName = coin.path.charAt(0).toUpperCase() + coin.path.slice(1) //name跳转 首字母大写
|
let jumpName = coin.path.charAt(0).toUpperCase() + coin.path.slice(1) //name跳转 首字母大写
|
||||||
console.log(jumpName,1366565,coin);
|
|
||||||
let url = `/${lang}/AccessMiningPool`
|
|
||||||
// 使用 name 进行导航,避免重复的路由参数
|
// 使用 name 进行导航,避免重复的路由参数
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name:'AccessMiningPool',
|
name:jumpName,
|
||||||
params: {
|
params: {
|
||||||
|
lang: lang,
|
||||||
coin: this.activeItemCoin.value,
|
coin: this.activeItemCoin.value,
|
||||||
imgUrl: this.activeItemCoin.imgUrl
|
imgUrl: this.activeItemCoin.imgUrl
|
||||||
},
|
|
||||||
|
|
||||||
|
},
|
||||||
replace: false // 保留历史记录,允许回退
|
replace: false // 保留历史记录,允许回退
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
// 移除开头的斜杠,统一处理路径格式
|
// 移除开头的斜杠,统一处理路径格式
|
||||||
// const cleanPath = path.startsWith('/') ? path.slice(1) : path;
|
const cleanPath = path.startsWith('/') ? path.slice(1) : path;
|
||||||
let cleanPath = `/${lang}/AccessMiningPool`
|
this.$router.push(`/${lang}/${cleanPath}`);
|
||||||
this.$router.push(cleanPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
jumpPage4(){
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/submitWorkOrder`);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
handleCommand(item) {},
|
handleCommand(item) {},
|
||||||
handleScroll(event) {
|
handleScroll(event) {
|
||||||
if (this.$route.path == "/") {
|
if (this.$route.path == "/") {
|
||||||
@@ -520,7 +511,6 @@ export default {
|
|||||||
// overflow-y: scroll;
|
// overflow-y: scroll;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// .headerBox{
|
// .headerBox{
|
||||||
|
|||||||
@@ -175,31 +175,8 @@
|
|||||||
<span class="line"></span>
|
<span class="line"></span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<!-- 帮助中心 -->
|
|
||||||
<li
|
<li
|
||||||
class="personalCenter"
|
|
||||||
:class="{
|
|
||||||
active: $route.path.includes(`/${$i18n.locale}/helpCenter`),
|
|
||||||
}"
|
|
||||||
@click="handelJump('helpCenter')"
|
|
||||||
>
|
|
||||||
{{ $t(`home.helpCenter`) }}
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="horizontalLine"
|
|
||||||
:class="{ hidden: $route.path.includes(`helpCenter`) }"
|
|
||||||
>
|
|
||||||
<span class="circular"></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<!-- 矿机租赁 -->
|
|
||||||
<!-- <li @click="handelMachineLease">
|
|
||||||
{{ $t(`home.machineLease`) }}
|
|
||||||
</li> -->
|
|
||||||
|
|
||||||
<!-- 工单管理 -->
|
|
||||||
<!-- <li
|
|
||||||
v-show="ManagementShow"
|
v-show="ManagementShow"
|
||||||
class="personalCenter"
|
class="personalCenter"
|
||||||
:class="{
|
:class="{
|
||||||
@@ -216,7 +193,7 @@
|
|||||||
<span class="circular"></span>
|
<span class="circular"></span>
|
||||||
<span class="line"></span>
|
<span class="line"></span>
|
||||||
</div>
|
</div>
|
||||||
</li> -->
|
</li>
|
||||||
|
|
||||||
<li class="langBox">
|
<li class="langBox">
|
||||||
<div class="LangLine"></div>
|
<div class="LangLine"></div>
|
||||||
@@ -253,26 +230,6 @@
|
|||||||
<li class="register" @click="handelRegister">
|
<li class="register" @click="handelRegister">
|
||||||
{{ $t(`user.register`) }}
|
{{ $t(`user.register`) }}
|
||||||
</li>
|
</li>
|
||||||
<!-- 帮助中心 -->
|
|
||||||
<li
|
|
||||||
class="personalCenter"
|
|
||||||
style="margin-left: 20px;"
|
|
||||||
:class="{
|
|
||||||
active: $route.path.includes(`/${$i18n.locale}/helpCenter`),
|
|
||||||
}"
|
|
||||||
@click="handelJump('helpCenter')"
|
|
||||||
>
|
|
||||||
{{ $t(`home.helpCenter`) }}
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="horizontalLine"
|
|
||||||
:class="{ hidden: $route.path.includes(`helpCenter`) }"
|
|
||||||
>
|
|
||||||
<span class="circular"></span>
|
|
||||||
<span class="line"></span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="langBox">
|
<li class="langBox">
|
||||||
<div class="LangLine"></div>
|
<div class="LangLine"></div>
|
||||||
<el-dropdown>
|
<el-dropdown>
|
||||||
@@ -339,8 +296,6 @@ export default {
|
|||||||
imgUrl:getImageUrl(`/img/nexa.png`) ,
|
imgUrl:getImageUrl(`/img/nexa.png`) ,
|
||||||
|
|
||||||
},
|
},
|
||||||
customerIsOnline: false,
|
|
||||||
userEmail:"",
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -397,8 +352,6 @@ export default {
|
|||||||
this.jurisdiction = JSON.parse(jurisdiction);
|
this.jurisdiction = JSON.parse(jurisdiction);
|
||||||
let currencyList = localStorage.getItem("currencyList");
|
let currencyList = localStorage.getItem("currencyList");
|
||||||
this.currencyList = JSON.parse(currencyList);
|
this.currencyList = JSON.parse(currencyList);
|
||||||
let userEmail = localStorage.getItem("userEmail");
|
|
||||||
this.userEmail = JSON.parse(userEmail);
|
|
||||||
window.addEventListener("setItem", () => {
|
window.addEventListener("setItem", () => {
|
||||||
let valueTaking = localStorage.getItem("token");
|
let valueTaking = localStorage.getItem("token");
|
||||||
this.token = JSON.parse(valueTaking);
|
this.token = JSON.parse(valueTaking);
|
||||||
@@ -412,8 +365,6 @@ export default {
|
|||||||
this.currencyList = JSON.parse(currencyList);
|
this.currencyList = JSON.parse(currencyList);
|
||||||
let active = localStorage.getItem(`activeItemCoin`)
|
let active = localStorage.getItem(`activeItemCoin`)
|
||||||
this.activeItem = JSON.parse(active)
|
this.activeItem = JSON.parse(active)
|
||||||
let userEmail = localStorage.getItem("userEmail");
|
|
||||||
this.userEmail = JSON.parse(userEmail);
|
|
||||||
|
|
||||||
if (this.jurisdiction && this.jurisdiction.roleKey == `admin`) {
|
if (this.jurisdiction && this.jurisdiction.roleKey == `admin`) {
|
||||||
this.ManagementShow = true;
|
this.ManagementShow = true;
|
||||||
@@ -431,15 +382,10 @@ export default {
|
|||||||
document.addEventListener("click", function () {
|
document.addEventListener("click", function () {
|
||||||
const dropdown = document.querySelector(".dropdown");
|
const dropdown = document.querySelector(".dropdown");
|
||||||
const arrow = document.querySelector(".arrow");
|
const arrow = document.querySelector(".arrow");
|
||||||
try {
|
|
||||||
if (dropdown.classList.contains("show")) {
|
if (dropdown.classList.contains("show")) {
|
||||||
dropdown.classList.remove("show");
|
dropdown.classList.remove("show");
|
||||||
arrow.classList.remove("up");
|
arrow.classList.remove("up");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -496,35 +442,11 @@ export default {
|
|||||||
// localStorage.setItem(`accountList`,JSON.stringify(this.accountList))
|
// localStorage.setItem(`accountList`,JSON.stringify(this.accountList))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// 修改 fetchUserid 方法,添加 token 检查
|
|
||||||
async fetchUserid(params) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
const res = await getUserid(params);
|
|
||||||
if (res && res.code == 200) {
|
|
||||||
|
|
||||||
this.customerIsOnline = res.data.customerIsOnline;
|
|
||||||
localStorage.setItem(`customerIsOnline`,JSON.stringify(this.customerIsOnline))
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("获取用户ID失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
async fetchSignOut() {
|
async fetchSignOut() {
|
||||||
const data = await getLogout();
|
const data = await getLogout();
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
// 调用 Vuex 的 logout action 清除前端状态
|
|
||||||
await this.$store.dispatch('logout')
|
|
||||||
const lang = this.$i18n.locale;
|
const lang = this.$i18n.locale;
|
||||||
|
|
||||||
this.fetchUserid({email:this.userEmail})
|
|
||||||
this.$router.push(`/${lang}`);
|
this.$router.push(`/${lang}`);
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleDropdownClick() {
|
handleDropdownClick() {
|
||||||
@@ -635,95 +557,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handelSignOut() {
|
handelSignOut() {
|
||||||
localStorage.setItem('cs_disconnect_all', Date.now().toString()); //告知客服页面断开连接
|
|
||||||
this.fetchSignOut();
|
this.fetchSignOut();
|
||||||
localStorage.removeItem(`token`);
|
localStorage.removeItem(`token`);
|
||||||
localStorage.removeItem("username");
|
localStorage.removeItem("username");
|
||||||
localStorage.removeItem("userName");
|
|
||||||
localStorage.removeItem("userEmail");
|
|
||||||
localStorage.removeItem("jurisdiction");
|
localStorage.removeItem("jurisdiction");
|
||||||
this.$addStorageEvent(1, `miningAccountList`, JSON.stringify(""));
|
this.$addStorageEvent(1, `miningAccountList`, JSON.stringify(""));
|
||||||
this.isLogin = false;
|
this.isLogin = false;
|
||||||
this.isDropdownVisible = false;
|
this.isDropdownVisible = false;
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 简单的AES加密函数
|
|
||||||
* @param {string} text - 要加密的文本
|
|
||||||
* @param {string} secretKey - 密钥
|
|
||||||
* @returns {string} 加密后的字符串
|
|
||||||
*/
|
|
||||||
encryptData(text, secretKey) {
|
|
||||||
try {
|
|
||||||
// 使用简单的XOR加密(生产环境建议使用更安全的加密库如crypto-js)
|
|
||||||
let encrypted = '';
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
|
||||||
encrypted += String.fromCharCode(text.charCodeAt(i) ^ secretKey.charCodeAt(i % secretKey.length));
|
|
||||||
}
|
|
||||||
return btoa(encrypted); // Base64编码
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加密失败:', error);
|
|
||||||
return text; // 如果加密失败,返回原文
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理机器租赁跳转,携带加密的用户参数
|
|
||||||
*/
|
|
||||||
handelMachineLease(){
|
|
||||||
try {
|
|
||||||
// 获取当前用户信息和其他需要传递的参数
|
|
||||||
|
|
||||||
const token =localStorage.getItem('token') || '';
|
|
||||||
const userEmail = localStorage.getItem('userEmail') || '';
|
|
||||||
const language = this.$i18n.locale || 'zh';
|
|
||||||
const username = localStorage.getItem('username') || '';
|
|
||||||
if (!token || !userEmail) {
|
|
||||||
this.$message.error("登录信息异常,请重新登录");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 定义加密密钥(生产环境应该从环境变量或配置文件中获取)
|
|
||||||
const secretKey = 'mining-pool-secret-key-2024';
|
|
||||||
|
|
||||||
// 准备要加密的敏感数据
|
|
||||||
const sensitiveData = {
|
|
||||||
token: token,
|
|
||||||
leasEmail: userEmail,
|
|
||||||
timestamp: Date.now()
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加密敏感数据
|
|
||||||
const encryptedData = this.encryptData(JSON.stringify(sensitiveData), secretKey);
|
|
||||||
|
|
||||||
// 构建带参数的URL(敏感数据加密,其他数据明文)
|
|
||||||
const baseUrl = "http://18.183.240.108:8080/";
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
data: encryptedData, // 加密的敏感数据
|
|
||||||
language: language,
|
|
||||||
username: username,
|
|
||||||
source: 'mining-pool', // 标识来源项目
|
|
||||||
version: '1.0' // 数据版本,用于兼容性
|
|
||||||
});
|
|
||||||
|
|
||||||
const urlWithParams = `${baseUrl}?${params.toString()}`;
|
|
||||||
|
|
||||||
// 当前窗口打开
|
|
||||||
window.open(urlWithParams, "_self");
|
|
||||||
|
|
||||||
// 记录跳转日志(用于调试,不记录敏感信息)
|
|
||||||
console.log('跳转到机器租赁系统,携带参数:', {
|
|
||||||
|
|
||||||
userEmail: userEmail ? '***' : '',
|
|
||||||
language,
|
|
||||||
source: 'mining-pool',
|
|
||||||
encrypted: true
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('跳转机器租赁系统时发生错误:', error);
|
|
||||||
this.$message.error("加载系统失败 稍后重试");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -854,11 +695,8 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.miningAccountTitle:hover {
|
.miningAccountTitle:hover {
|
||||||
color: #6e3edb !important;
|
color: #6e3edb !important;
|
||||||
|
|
||||||
}
|
}
|
||||||
.hidden {
|
.hidden {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -907,13 +745,10 @@ export default {
|
|||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between; /* 保持logo在左,导航在右 */
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 95%;
|
||||||
|
|
||||||
margin: 0 auto; /* 居中显示 */
|
|
||||||
padding: 0 2.5%; /* 使用padding替代固定宽度 */
|
|
||||||
/* outline: 1px solid red; */
|
/* outline: 1px solid red; */
|
||||||
// outline: 1PX solid red;
|
// outline: 1PX solid red;
|
||||||
// padding: 0px 5%;
|
// padding: 0px 5%;
|
||||||
@@ -921,35 +756,30 @@ export default {
|
|||||||
// background: #21A0FF;
|
// background: #21A0FF;
|
||||||
}
|
}
|
||||||
.logo {
|
.logo {
|
||||||
flex: 0 0 auto; /* 不伸缩,保持固定大小 */
|
width: 18%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end; /* 右对齐 */
|
justify-content: right;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
width: 300px; /* 固定宽度,给导航留出更多空间 */
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: auto; /* 保持比例 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.topMenu {
|
.topMenu {
|
||||||
flex: 1; /* 占据剩余空间 */
|
width: 80%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end; /* 右对齐 */
|
justify-content: end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-width: 0; /* 允许收缩 */
|
|
||||||
// background: goldenrod;
|
// background: goldenrod;
|
||||||
|
|
||||||
|
|
||||||
.afterLoggingIn {
|
.afterLoggingIn {
|
||||||
|
min-width: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end; /* 右对齐 */
|
justify-content: right;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: nowrap; /* 防止换行 */
|
|
||||||
width: auto; /* 自适应宽度 */
|
|
||||||
// background: #6E3EDB;
|
// background: #6E3EDB;
|
||||||
|
|
||||||
.langBox {
|
.langBox {
|
||||||
@@ -994,15 +824,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.notLoggedIn {
|
.notLoggedIn {
|
||||||
display: flex;
|
width: 40%;
|
||||||
justify-content: flex-end; /* 右对齐 */
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px; /* 增加间距 */
|
|
||||||
|
|
||||||
li {
|
li {
|
||||||
flex: 0 0 auto; /* 不伸缩,保持内容大小 */
|
margin-left: 1%;
|
||||||
white-space: nowrap; /* 防止文字换行 */
|
|
||||||
padding: 0 6px; /* 减少内边距 */
|
|
||||||
}
|
}
|
||||||
.langBox {
|
.langBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1011,7 +836,7 @@ export default {
|
|||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
.register.register {
|
.register.register {
|
||||||
padding: 5px 30px;
|
padding: 1px 30px;
|
||||||
}
|
}
|
||||||
.LangLine {
|
.LangLine {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
@@ -1022,28 +847,28 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.menuBox {
|
.menuBox {
|
||||||
|
min-width: 42% !important;
|
||||||
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end; /* 右对齐 */
|
justify-content: end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0;
|
margin: 0%;
|
||||||
gap: 12px; /* 增加间距 */
|
|
||||||
flex-wrap: nowrap; /* 防止换行 */
|
|
||||||
// background: #fff;
|
// background: #fff;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
// width: calc(100% / 5);
|
||||||
height: 45%;
|
height: 45%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-left: 3%;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
// transition: all 0.3s linear;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex: 0 0 auto; /* 不伸缩,保持内容大小 */
|
min-width: 61px;
|
||||||
white-space: nowrap; /* 防止文字换行 */
|
|
||||||
padding: 0 6px; /* 减少内边距 */
|
|
||||||
min-width: auto; /* 移除最小宽度限制 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li:hover {
|
li:hover {
|
||||||
@@ -1071,7 +896,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" >
|
||||||
.el-submenu__title:hover {
|
.el-submenu__title:hover {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
@@ -1103,48 +928,4 @@ export default {
|
|||||||
.el-menu.el-menu--horizontal {
|
.el-menu.el-menu--horizontal {
|
||||||
border-bottom: 0px !important;
|
border-bottom: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 - 小屏幕适配 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.header {
|
|
||||||
padding: 0 1%; /* 减少内边距 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
min-width: 80px; /* 减少logo最小宽度 */
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 80px; /* 减小logo尺寸 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuBox {
|
|
||||||
gap: 4px; /* 减少间距 */
|
|
||||||
|
|
||||||
li {
|
|
||||||
font-size: 0.8rem; /* 减小字体 */
|
|
||||||
padding: 0 4px; /* 减少内边距 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.topMenu .afterLoggingIn .langBox {
|
|
||||||
width: 50px; /* 减小语言选择框宽度 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 超小屏幕 - 隐藏部分菜单项 */
|
|
||||||
@media (max-width: 480px) {
|
|
||||||
.menuBox li:not(.home):not(.langBox) {
|
|
||||||
display: none; /* 只显示首页和语言选择 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuBox {
|
|
||||||
gap: 2px;
|
|
||||||
|
|
||||||
li {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -46,7 +46,6 @@ export const AccessMiningPool_zh = {
|
|||||||
dgboCourse:"Dgb(odocrypt) 挖矿教程",
|
dgboCourse:"Dgb(odocrypt) 挖矿教程",
|
||||||
ENXcourse:"Entropyx(Enx) 挖矿教程",
|
ENXcourse:"Entropyx(Enx) 挖矿教程",
|
||||||
alphCourse:"Alephium(alph) 挖矿教程",
|
alphCourse:"Alephium(alph) 挖矿教程",
|
||||||
xmrCourse:"xmr(monero) 挖矿教程",
|
|
||||||
rxdIncome1:"1. 在您添加完挖矿钱包后,即可在您的Rxd矿机上配置相关参数,开启Rxd挖矿。",
|
rxdIncome1:"1. 在您添加完挖矿钱包后,即可在您的Rxd矿机上配置相关参数,开启Rxd挖矿。",
|
||||||
Adaptation:"适配性",
|
Adaptation:"适配性",
|
||||||
amount:"最小起付额",
|
amount:"最小起付额",
|
||||||
@@ -72,8 +71,6 @@ export const AccessMiningPool_zh = {
|
|||||||
conditionDgbo:"40高度",
|
conditionDgbo:"40高度",
|
||||||
conditionMona:"100高度",
|
conditionMona:"100高度",
|
||||||
conditionAlph:"500分钟",
|
conditionAlph:"500分钟",
|
||||||
conditionXmr:"60高度",
|
|
||||||
conditionXtm:"360高度",
|
|
||||||
conditionEnx:"",
|
conditionEnx:"",
|
||||||
intervalNexa:"120秒",
|
intervalNexa:"120秒",
|
||||||
intervalRxd:"300秒",
|
intervalRxd:"300秒",
|
||||||
@@ -83,9 +80,7 @@ export const AccessMiningPool_zh = {
|
|||||||
intervalDgbo:"15秒",
|
intervalDgbo:"15秒",
|
||||||
intervalMona:"90秒",
|
intervalMona:"90秒",
|
||||||
intervalAlph:"16秒",
|
intervalAlph:"16秒",
|
||||||
intervalXtm:"120秒",
|
|
||||||
intervalEnx:"1秒",
|
intervalEnx:"1秒",
|
||||||
intervalXmr:"120秒",
|
|
||||||
estimatedTimeNexa:"≈ 7天",
|
estimatedTimeNexa:"≈ 7天",
|
||||||
estimatedTimeRxd:"≈ 8.3小时",
|
estimatedTimeRxd:"≈ 8.3小时",
|
||||||
estimatedTimeGrs:"≈ 2.3小时",
|
estimatedTimeGrs:"≈ 2.3小时",
|
||||||
@@ -95,8 +90,7 @@ export const AccessMiningPool_zh = {
|
|||||||
estimatedTimeMona:"≈ 2.5小时",
|
estimatedTimeMona:"≈ 2.5小时",
|
||||||
estimatedTimeAlph:"500分钟",
|
estimatedTimeAlph:"500分钟",
|
||||||
estimatedTimeEnx:"",
|
estimatedTimeEnx:"",
|
||||||
estimatedTimeXtm:"≈ 12小时",
|
describeNexa:"例如1-1日获得了1000000 NEXA奖励,则该笔奖励会在大约7天之后(1-8日)支付,具体取决于实际区块高度",
|
||||||
describeNexa:"例如1月1日获得了1000000 NEXA奖励,则该笔奖励会在大约7天之后(1月8日)支付,具体取决于实际区块高度",
|
|
||||||
describeAlph:"alph是固定成熟时间,而非区块高度",
|
describeAlph:"alph是固定成熟时间,而非区块高度",
|
||||||
describeGrs:"",
|
describeGrs:"",
|
||||||
describeDgbs:"",
|
describeDgbs:"",
|
||||||
@@ -105,13 +99,11 @@ export const AccessMiningPool_zh = {
|
|||||||
describeMona:"",
|
describeMona:"",
|
||||||
describeRxd:"",
|
describeRxd:"",
|
||||||
describeEnx:"",
|
describeEnx:"",
|
||||||
describeXtm:"",
|
|
||||||
condition:"成熟条件",
|
condition:"成熟条件",
|
||||||
interval:"出块间隔",
|
interval:"出块间隔",
|
||||||
estimatedTime:"预估时间",
|
estimatedTime:"预估时间",
|
||||||
describe:"说明",
|
describe:"说明",
|
||||||
timeLimited:"限时",
|
timeLimited:"限时",
|
||||||
backMenu:"返回挖矿教程目录",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +179,6 @@ export const AccessMiningPool_en = {
|
|||||||
conditionMona:"100 height",
|
conditionMona:"100 height",
|
||||||
conditionAlph:"500 minutes",
|
conditionAlph:"500 minutes",
|
||||||
conditionEnx:"",
|
conditionEnx:"",
|
||||||
conditionXtm:"360 height",
|
|
||||||
intervalNexa:"120 seconds",
|
intervalNexa:"120 seconds",
|
||||||
intervalRxd:"300 seconds",
|
intervalRxd:"300 seconds",
|
||||||
intervalGrs:"60 seconds",
|
intervalGrs:"60 seconds",
|
||||||
@@ -197,19 +188,16 @@ export const AccessMiningPool_en = {
|
|||||||
intervalMona:"90 seconds",
|
intervalMona:"90 seconds",
|
||||||
intervalAlph:"16 seconds",
|
intervalAlph:"16 seconds",
|
||||||
intervalEnx:"1 second",
|
intervalEnx:"1 second",
|
||||||
intervalXtm:"120 seconds",
|
|
||||||
estimatedTimeNexa:"≈ 7 days",
|
estimatedTimeNexa:"≈ 7 days",
|
||||||
estimatedTimeRxd:"≈ 8.3 hours",
|
estimatedTimeRxd:"≈ 8.3 hours",
|
||||||
estimatedTimeGrs:"≈ 2.3 hours",
|
estimatedTimeGrs:"≈ 2.3 hours",
|
||||||
estimatedTimeDgbs:"≈ 10 minutes",
|
estimatedTimeDgbs:"≈ 10 minutes",
|
||||||
estimatedTimeDgbq:"≈ 10 minutes",
|
estimatedTimeDgbq:"≈ 10 minutes",
|
||||||
estimatedTimeDgbo:"≈ 10 minutes",
|
estimatedTimeDgbo:"≈ 10 minutes",
|
||||||
estimatedTimeMona:"≈ 2.5 hours",
|
estimatedTimeMona:"≈ 25 hours",
|
||||||
estimatedTimeAlph:" 500 minutes",
|
estimatedTimeAlph:" 500 minutes",
|
||||||
estimatedTimeEnx:"",
|
estimatedTimeEnx:"",
|
||||||
estimatedTimeXmr:"≈ 2 hours",
|
describeNexa:"For example, if a 1,000,000 NEXA reward was earned on 1-1, that reward will be paid out approximately 7 days later (1-8), depending on actual block heights",
|
||||||
estimatedTimeXtm:"≈ 12 hours",
|
|
||||||
describeNexa:"For example, if you receive a reward of 1000000 NEXA on January 1st, the reward will be paid approximately 7 days later (January 8th), depending on the actual block height",
|
|
||||||
describeAlph:"alph is a fixed maturity time, not a block height",
|
describeAlph:"alph is a fixed maturity time, not a block height",
|
||||||
describeGrs:"",
|
describeGrs:"",
|
||||||
describeDgbs:"",
|
describeDgbs:"",
|
||||||
@@ -218,8 +206,6 @@ export const AccessMiningPool_en = {
|
|||||||
describeMona:"",
|
describeMona:"",
|
||||||
describeRxd:"",
|
describeRxd:"",
|
||||||
describeEnx:"",
|
describeEnx:"",
|
||||||
describeXmr:"",
|
|
||||||
describeXtm:"",
|
|
||||||
allocationExplanation:"Mining Pool Allocation and Transfer Rules",
|
allocationExplanation:"Mining Pool Allocation and Transfer Rules",
|
||||||
condition:"Maturity conditions",
|
condition:"Maturity conditions",
|
||||||
interval:"Chunking interval",
|
interval:"Chunking interval",
|
||||||
@@ -228,7 +214,5 @@ export const AccessMiningPool_en = {
|
|||||||
ENXcourse:"Entropyx(Enx) Mining Tutorial",
|
ENXcourse:"Entropyx(Enx) Mining Tutorial",
|
||||||
timeLimited:"Time limited",
|
timeLimited:"Time limited",
|
||||||
alphCourse:"Alephium(alph) Mining Tutorial",
|
alphCourse:"Alephium(alph) Mining Tutorial",
|
||||||
xmrCourse:"Xmr(monero) Mining Tutorial",
|
|
||||||
backMenu:"Return to Table of Contents",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
export const ChatWidget_zh = {
|
|
||||||
chat:{
|
|
||||||
|
|
||||||
title: '在线客服',
|
|
||||||
welcome: '欢迎使用在线客服,请问有什么可以帮您?',
|
|
||||||
placeholder: '请输入您的消息...',
|
|
||||||
send: '发送',
|
|
||||||
close: '关闭',
|
|
||||||
inputPlaceholder:"请输入您的问题...",
|
|
||||||
onlyImages:"只能上传图片文件!",
|
|
||||||
imageTooLarge:"图片大小不能超过5MB!",
|
|
||||||
imageReceived:"已收到您的图片,我们会尽快处理您的问题。",
|
|
||||||
|
|
||||||
networkError:"网络连接已断开,请刷新页面重试",
|
|
||||||
openCustomerService:"打开客服聊天",
|
|
||||||
connectToCustomerService:"正在连接客服系统...",
|
|
||||||
connectionFailed:"连接失败,请刷新页面重试",
|
|
||||||
tryConnectingAgain:"重试连接",
|
|
||||||
loading:"加载中...",
|
|
||||||
loadMore:"加载更多历史消息",
|
|
||||||
welcomeToUse:"欢迎使用在线客服,请问有什么可以帮您?",
|
|
||||||
picture:"聊天图片",
|
|
||||||
read:"已读",
|
|
||||||
unread:"未读",
|
|
||||||
subscriptionFailed:"消息订阅失败,可能无法接收新消息",
|
|
||||||
break:"连接断开",
|
|
||||||
retry:"秒后重试",
|
|
||||||
disconnectWaiting:"断线重连中...",
|
|
||||||
sendFailed:"发送消息失败,请重试",
|
|
||||||
noHistory:"暂无历史消息",
|
|
||||||
historicalFailure:"加载历史消息失败,请重试",
|
|
||||||
loadingHistory:"正在加载更多历史消息...",
|
|
||||||
noMoreHistory:"没有更多历史消息了",
|
|
||||||
Loaded:"已加载历史消息",
|
|
||||||
newMessage:"新消息",
|
|
||||||
pictureMessage:"图片消息",
|
|
||||||
initializationFailed:"初始化失败,请刷新页面重试",
|
|
||||||
beSorry:"抱歉,我暂时无法回答这个问题。请排队等待人工客服或提交工单。",
|
|
||||||
today:"今天",
|
|
||||||
yesterday:"昨天",
|
|
||||||
canOnlyUploadImages:"只能上传图片文件!",
|
|
||||||
imageSizeExceeded:"图片大小不能超过5MB!",
|
|
||||||
uploading:"正在上传图片...",
|
|
||||||
pictureFailed:"发送图片失败,请重试",
|
|
||||||
readImage:"读取图片失败,请重试",
|
|
||||||
processingFailed:"图片处理失败,请重试",
|
|
||||||
Disconnected:"连接已断开",
|
|
||||||
reconnecting:"正在连接...",
|
|
||||||
contactList:"联系列表",
|
|
||||||
search:"搜索最近联系人",
|
|
||||||
tourist:"游客",
|
|
||||||
important:"重要",
|
|
||||||
markAsImportant:"标记为重要",
|
|
||||||
cancelImportant:"已取消重要标记",
|
|
||||||
markingFailed:"标记操作失败,请重试",
|
|
||||||
Marked:"已标记为重要",
|
|
||||||
select:"请选择联系人",
|
|
||||||
notSelected:"您尚未选择联系人",
|
|
||||||
None:"暂无消息记录",
|
|
||||||
sendPicture:"发送图片",
|
|
||||||
inputMessage:"请输入消息,按Enter键发送,按Ctrl+Enter键换行",
|
|
||||||
bottom:"回到底部",
|
|
||||||
Preview:"预览图片",
|
|
||||||
chatRoom:"聊天室",
|
|
||||||
CLOSED:"已关闭",
|
|
||||||
picture2:"图片",
|
|
||||||
Unnamed:"未命名聊天室",
|
|
||||||
noNewsAtTheMoment:"暂无未读消息",
|
|
||||||
contactFailed:"加载更多联系人失败",
|
|
||||||
listException:"获取聊天室列表异常",
|
|
||||||
my:"我",
|
|
||||||
unknownSender:"未知发送者",
|
|
||||||
recordFailed:"加载聊天记录失败",
|
|
||||||
messageException:"加载消息异常",
|
|
||||||
chooseFirst:"请先选择联系人",
|
|
||||||
chatDisconnected:"聊天连接已断开,请刷新页面重试",
|
|
||||||
pictureSuccessful:"图片已发送",
|
|
||||||
history:"历史记录",
|
|
||||||
loadFailed:"加载失败",
|
|
||||||
guestNotice:"您当前以游客身份聊天,聊天记录将不会保存。",
|
|
||||||
guestNotice2:"后即可保存聊天记录",
|
|
||||||
loginToSave:"登录",
|
|
||||||
server500:"服务器暂时不可用,请稍后重试",
|
|
||||||
CheckNetwork:"连接失败,请检查网络后重试",
|
|
||||||
attemptToReconnect:"连接已断开,正在尝试重连...",
|
|
||||||
retryFailed:"重试连接失败,请刷新页面",
|
|
||||||
maxConnectionsError:"连接数已达上限,请刷新页面重试",
|
|
||||||
ipLimitError:"本机连接数已达上限,请刷新页面重试",
|
|
||||||
serverLimitError:"服务器连接数已达上限,请稍后刷新重试",
|
|
||||||
identityError:"用户身份设置失败,请刷新页面重试",
|
|
||||||
emailError:"用户信息获取失败,请刷新页面重试",
|
|
||||||
refreshPage:"刷新页面",
|
|
||||||
reconnectSuccess:"重新连接成功",
|
|
||||||
sendMessageEmpty:"发送消息不能为空",
|
|
||||||
unableToSubscribe:"连接状态异常,刷新页面重试",
|
|
||||||
conflict:"连接异常,可能是多窗口冲突,请关闭其他窗口重试",
|
|
||||||
abnormal:"连接异常",
|
|
||||||
networkAnomaly:"网络连接异常",
|
|
||||||
customerServiceOffline:"客服离线,请登录账号发送留言消息",
|
|
||||||
contentMax:"超出发送内容大小限制,请删除部分内容(300字以内)",
|
|
||||||
failInSend:"发送失败,请重试",
|
|
||||||
connectionLimitError:"连接数已达上限,请关闭一些窗口后刷新重试",
|
|
||||||
serverBusy:"服务器繁忙,请稍后刷新重试",
|
|
||||||
connectionTimedOut:"连接超时,稍后重试...",
|
|
||||||
reconnectFailed:"重连失败,请稍后重试",
|
|
||||||
serviceConfigurationError:"服务配置异常,请稍后重试",
|
|
||||||
serviceAddressUnavailable:"服务地址不可用,请稍后重试",
|
|
||||||
connectionFailedService:"无法连接到服务器,请稍后重试",
|
|
||||||
connectionFailedCustomer:"连接客服系统失败,请检查网络或稍后重试",
|
|
||||||
logoutSyncNotice:"检测到您已在其他窗口退出登录,当前窗口将自动跳转",
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ChatWidget_en = {
|
|
||||||
|
|
||||||
|
|
||||||
chat:{
|
|
||||||
title: 'Online Customer Service',
|
|
||||||
welcome: 'Welcome to the online customer service, what can I help you with?',
|
|
||||||
placeholder: 'Please enter your message...',
|
|
||||||
send: 'Send',
|
|
||||||
close: 'Close',
|
|
||||||
inputPlaceholder:"Please enter your question...",
|
|
||||||
onlyImages:"Only image files can be uploaded!",
|
|
||||||
imageTooLarge:"The image size cannot exceed 5MB!",
|
|
||||||
imageReceived:"We have received your image, and we will handle your question as soon as possible.",
|
|
||||||
|
|
||||||
networkError: "Network disconnected, please refresh page",
|
|
||||||
openCustomerService: "Open customer service chat",
|
|
||||||
connectToCustomerService: "Connecting to customer service...",
|
|
||||||
connectionFailed: "Connection failed, please refresh page",
|
|
||||||
tryConnectingAgain: "Retry connection",
|
|
||||||
loading: "Loading...",
|
|
||||||
loadMore: "Load more history",
|
|
||||||
welcomeToUse: "Welcome to online service, how can I help you?",
|
|
||||||
picture: "Chat image",
|
|
||||||
read: "Read",
|
|
||||||
unread: "Unread",
|
|
||||||
subscriptionFailed: "Message subscription failed",
|
|
||||||
break: "Connection lost",
|
|
||||||
retry: "Retry in seconds",
|
|
||||||
disconnectWaiting: "connecting...",
|
|
||||||
sendFailed: "Send failed, please retry",
|
|
||||||
noHistory: "No history",
|
|
||||||
historicalFailure: "Failed to load history",
|
|
||||||
loadingHistory: "Loading more history...",
|
|
||||||
noMoreHistory: "No more history",
|
|
||||||
Loaded: "History loaded",
|
|
||||||
newMessage: "New message",
|
|
||||||
pictureMessage: "Image message",
|
|
||||||
initializationFailed: "Initialization failed, please refresh",
|
|
||||||
beSorry: "Sorry, I cannot answer this. Please wait for agent or submit ticket",
|
|
||||||
today: "Today",
|
|
||||||
yesterday: "Yesterday",
|
|
||||||
canOnlyUploadImages: "Only image files allowed",
|
|
||||||
imageSizeExceeded: "Image size exceeds 5MB",
|
|
||||||
uploading: "Uploading image...",
|
|
||||||
pictureFailed: "Failed to send image",
|
|
||||||
readImage: "Failed to read image",
|
|
||||||
processingFailed: "Image processing failed",
|
|
||||||
Disconnected: "Disconnected",
|
|
||||||
reconnecting: "Reconnecting...",
|
|
||||||
contactList: "Contact list",
|
|
||||||
search: "Search contacts",
|
|
||||||
tourist: "Guest",
|
|
||||||
important: "Important",
|
|
||||||
markAsImportant: "Mark as important",
|
|
||||||
cancelImportant: "Unmarked as important",
|
|
||||||
markingFailed: "Marking failed",
|
|
||||||
select: "Select contact",
|
|
||||||
notSelected: "No contact selected",
|
|
||||||
None: "No messages",
|
|
||||||
sendPicture: "Send image",
|
|
||||||
inputMessage: "Type message, Enter to send, Ctrl+Enter for new line",
|
|
||||||
bottom: "to bottom",
|
|
||||||
Preview: "Preview image",
|
|
||||||
chatRoom: "Chat room",
|
|
||||||
CLOSED: "Closed",
|
|
||||||
picture2: "Image",
|
|
||||||
Unnamed: "Unnamed chat",
|
|
||||||
noNewsAtTheMoment: "No unread messages",
|
|
||||||
contactFailed: "Failed to load contacts",
|
|
||||||
listException: "Failed to get chat list",
|
|
||||||
my: "Me",
|
|
||||||
unknownSender: "Unknown sender",
|
|
||||||
recordFailed: "Failed to load chat records",
|
|
||||||
messageException: "Failed to load messages",
|
|
||||||
chooseFirst: "Please select contact first",
|
|
||||||
chatDisconnected: "Chat disconnected, please refresh",
|
|
||||||
pictureSuccessful: "Image sent",
|
|
||||||
history:"History",
|
|
||||||
loadFailed:"Load Fail",
|
|
||||||
Marked:"Marked as important",
|
|
||||||
guestNotice:"You are currently chatting as a guest, and your chat history will not be saved.",
|
|
||||||
guestNotice2:" to save chat history",
|
|
||||||
loginToSave:"Login",
|
|
||||||
server500:"The server is temporarily unavailable, please try again later",
|
|
||||||
CheckNetwork:"Connection failed, please check the network and try again",
|
|
||||||
attemptToReconnect:"Connection lost, attempting to reconnect...",
|
|
||||||
retryFailed:"Retry connection failed, please refresh page",
|
|
||||||
maxConnectionsError:"Connection limit reached, please refresh page",
|
|
||||||
ipLimitError:"Connection limit reached, please refresh page",
|
|
||||||
serverLimitError:"Connection limit reached, please try again later",
|
|
||||||
identityError:"Failed to set user identity, please refresh page",
|
|
||||||
emailError:"Failed to get user information, please refresh page",
|
|
||||||
refreshPage:"Refresh page",
|
|
||||||
reconnectSuccess:"Reconnect successfully",
|
|
||||||
sendMessageEmpty:"Message cannot be empty",
|
|
||||||
unableToSubscribe:"Connection status abnormal, please refresh the page",
|
|
||||||
conflict:"Connection exception, possibly due to multiple window conflicts, please close other windows and try again",
|
|
||||||
abnormal:"Connection exception",
|
|
||||||
networkAnomaly:"Network connection exception",
|
|
||||||
customerServiceOffline:"Customer service offline, please login to send message",
|
|
||||||
contentMax:"Content exceeds the size limit, please delete some content(300 characters or less)",
|
|
||||||
failInSend:"Failed to send, please try again",
|
|
||||||
connectionLimitError:"Connection limit reached, please close some windows and refresh to try again",
|
|
||||||
serverBusy:"Server busy, please refresh later",
|
|
||||||
connectionTimedOut:"Connection timed out, please try again later",
|
|
||||||
reconnectFailed:"Reconnect failed, please try again later",
|
|
||||||
serviceConfigurationError:"Service configuration exception, please try again later",
|
|
||||||
serviceAddressUnavailable:"Service address unavailable, please try again later",
|
|
||||||
connectionFailedService:"Failed to connect to the server, please try again later",
|
|
||||||
connectionFailedCustomer:"Failed to connect to the customer service system, please check the network or try again later",
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,190 +0,0 @@
|
|||||||
/**
|
|
||||||
* 公告中心页面国际化文件
|
|
||||||
* 包含公告中心页面相关的中英文翻译
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 中文翻译
|
|
||||||
export const announcements_zh = {
|
|
||||||
// 页面标题和导航
|
|
||||||
title: '公告中心',
|
|
||||||
latestTitle: '最新公告',
|
|
||||||
searchPlaceholder: '搜索',
|
|
||||||
|
|
||||||
// 面包屑导航
|
|
||||||
homeCenter: '首页中心',
|
|
||||||
|
|
||||||
// 公告相关
|
|
||||||
viewAll: '查看所有',
|
|
||||||
articles: '篇文章',
|
|
||||||
noData: '暂无公告',
|
|
||||||
loadError: '加载公告失败',
|
|
||||||
|
|
||||||
// 公告类型
|
|
||||||
importantNotice: '重要通知',
|
|
||||||
systemAnnouncement: '系统公告',
|
|
||||||
marketDynamic: '市场动态',
|
|
||||||
serviceNotice: '服务通知',
|
|
||||||
faultDescription: '故障说明',
|
|
||||||
offlineNotice: '下线通知',
|
|
||||||
|
|
||||||
// 时间相关
|
|
||||||
today: '今天',
|
|
||||||
yesterday: '昨天',
|
|
||||||
daysAgo: '天前',
|
|
||||||
|
|
||||||
// 操作
|
|
||||||
back: '返回',
|
|
||||||
refresh: '刷新',
|
|
||||||
search: '搜索',
|
|
||||||
reset: '重置',
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
total: '共',
|
|
||||||
page: '页',
|
|
||||||
items: '条',
|
|
||||||
goToPage: '跳至',
|
|
||||||
|
|
||||||
// 错误信息
|
|
||||||
networkError: '网络连接失败,请检查网络设置',
|
|
||||||
serverError: '服务器异常,请稍后重试',
|
|
||||||
dataError: '数据加载失败',
|
|
||||||
|
|
||||||
// 提示信息
|
|
||||||
searchTip: '请输入关键词进行搜索',
|
|
||||||
noSearchResult: '未找到相关公告',
|
|
||||||
loadingTip: '正在加载...',
|
|
||||||
|
|
||||||
// 公告状态
|
|
||||||
published: '已发布',
|
|
||||||
draft: '草稿',
|
|
||||||
archived: '已归档',
|
|
||||||
|
|
||||||
// 公告详情
|
|
||||||
detail: '详情',
|
|
||||||
content: '内容',
|
|
||||||
publishTime: '发布时间',
|
|
||||||
updateTime: '更新时间',
|
|
||||||
author: '作者',
|
|
||||||
category: '分类',
|
|
||||||
tags: '标签',
|
|
||||||
readCount: '阅读量',
|
|
||||||
|
|
||||||
// 操作按钮
|
|
||||||
viewDetail: '查看详情',
|
|
||||||
share: '分享',
|
|
||||||
favorite: '收藏',
|
|
||||||
print: '打印',
|
|
||||||
download: '下载',
|
|
||||||
|
|
||||||
// 筛选和排序
|
|
||||||
filter: '筛选',
|
|
||||||
sort: '排序',
|
|
||||||
sortByTime: '按时间排序',
|
|
||||||
sortByPopularity: '按热度排序',
|
|
||||||
filterByType: '按类型筛选',
|
|
||||||
filterByDate: '按日期筛选',
|
|
||||||
allTypes: '全部类型',
|
|
||||||
allDates: '全部日期',
|
|
||||||
|
|
||||||
// 高级搜索
|
|
||||||
advancedSearch: '高级搜索',
|
|
||||||
searchByTitle: '按标题搜索',
|
|
||||||
searchByContent: '按内容搜索',
|
|
||||||
searchByAuthor: '按作者搜索',
|
|
||||||
dateRange: '日期范围',
|
|
||||||
startDate: '开始日期',
|
|
||||||
endDate: '结束日期'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 英文翻译
|
|
||||||
export const announcements_en = {
|
|
||||||
// 页面标题和导航
|
|
||||||
title: 'Announcement Center',
|
|
||||||
latestTitle: 'Latest Announcements',
|
|
||||||
searchPlaceholder: 'Search',
|
|
||||||
|
|
||||||
// 面包屑导航
|
|
||||||
homeCenter: 'Home Center',
|
|
||||||
|
|
||||||
// 公告相关
|
|
||||||
viewAll: 'View All',
|
|
||||||
articles: 'Articles',
|
|
||||||
noData: 'No announcements',
|
|
||||||
loadError: 'Failed to load announcements',
|
|
||||||
|
|
||||||
// 公告类型
|
|
||||||
importantNotice: 'Important Notice',
|
|
||||||
systemAnnouncement: 'System Announcement',
|
|
||||||
marketDynamic: 'Market Dynamic',
|
|
||||||
serviceNotice: 'Service Notice',
|
|
||||||
faultDescription: 'Fault Description',
|
|
||||||
offlineNotice: 'Offline Notice',
|
|
||||||
|
|
||||||
// 时间相关
|
|
||||||
today: 'Today',
|
|
||||||
yesterday: 'Yesterday',
|
|
||||||
daysAgo: 'days ago',
|
|
||||||
|
|
||||||
// 操作
|
|
||||||
back: 'Back',
|
|
||||||
refresh: 'Refresh',
|
|
||||||
search: 'Search',
|
|
||||||
reset: 'Reset',
|
|
||||||
|
|
||||||
// 分页
|
|
||||||
total: 'Total',
|
|
||||||
page: 'Page',
|
|
||||||
items: 'Items',
|
|
||||||
goToPage: 'Go to',
|
|
||||||
|
|
||||||
// 错误信息
|
|
||||||
networkError: 'Network connection failed, please check network settings',
|
|
||||||
serverError: 'Server error, please try again later',
|
|
||||||
dataError: 'Data loading failed',
|
|
||||||
|
|
||||||
// 提示信息
|
|
||||||
searchTip: 'Please enter keywords to search',
|
|
||||||
noSearchResult: 'No related announcements found',
|
|
||||||
loadingTip: 'Loading...',
|
|
||||||
|
|
||||||
// 公告状态
|
|
||||||
published: 'Published',
|
|
||||||
draft: 'Draft',
|
|
||||||
archived: 'Archived',
|
|
||||||
|
|
||||||
// 公告详情
|
|
||||||
detail: 'Detail',
|
|
||||||
content: 'Content',
|
|
||||||
publishTime: 'Publish Time',
|
|
||||||
updateTime: 'Update Time',
|
|
||||||
author: 'Author',
|
|
||||||
category: 'Category',
|
|
||||||
tags: 'Tags',
|
|
||||||
readCount: 'Read Count',
|
|
||||||
|
|
||||||
// 操作按钮
|
|
||||||
viewDetail: 'View Detail',
|
|
||||||
share: 'Share',
|
|
||||||
favorite: 'Favorite',
|
|
||||||
print: 'Print',
|
|
||||||
download: 'Download',
|
|
||||||
|
|
||||||
// 筛选和排序
|
|
||||||
filter: 'Filter',
|
|
||||||
sort: 'Sort',
|
|
||||||
sortByTime: 'Sort by Time',
|
|
||||||
sortByPopularity: 'Sort by Popularity',
|
|
||||||
filterByType: 'Filter by Type',
|
|
||||||
filterByDate: 'Filter by Date',
|
|
||||||
allTypes: 'All Types',
|
|
||||||
allDates: 'All Dates',
|
|
||||||
|
|
||||||
// 高级搜索
|
|
||||||
advancedSearch: 'Advanced Search',
|
|
||||||
searchByTitle: 'Search by Title',
|
|
||||||
searchByContent: 'Search by Content',
|
|
||||||
searchByAuthor: 'Search by Author',
|
|
||||||
dateRange: 'Date Range',
|
|
||||||
startDate: 'Start Date',
|
|
||||||
endDate: 'End Date'
|
|
||||||
};
|
|
||||||
@@ -76,8 +76,6 @@ export const api_zh = {
|
|||||||
aCertainMiner: "挖矿账户下对应的某矿工号",
|
aCertainMiner: "挖矿账户下对应的某矿工号",
|
||||||
miningMachineHistory24h: "指定矿机历史24h平均算力",
|
miningMachineHistory24h: "指定矿机历史24h平均算力",
|
||||||
realTimeMiningMachine24h30m: "指定矿机最近24h算力(30m平均算力)",
|
realTimeMiningMachine24h30m: "指定矿机最近24h算力(30m平均算力)",
|
||||||
backMenu:"返回目录",
|
|
||||||
catalogue:"目录:",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +112,6 @@ export const api_en = {
|
|||||||
"overviewOfMiningPool": "Overview of Mining Pool", "jurisdiction": "Required permissions", "parameter": "Request parameters", "currency": "currency", "response": "Response parameters", "serviceCharge": "Mining pool handling fee", "minimumPaymentAmount": "Minimum payment amount", "latelyPower24h": "Last seven days' computing power (24-hour average)", "Power24h": "Latest computing power of mining pool (24-hour average)", "height": "The current height of the mining pool", "currentMiners": "The current number of miners in the mining pool", "eachState": "Number of miners in each state", "realTimePower": "Real time computing power of mining pool", "averagePower30m": "Current average computing power of 30m", "averagePower24h": "Current 24-hour average computing power", "Company": "Company", "historyPower": "Overview of Mining Pool Historical Computing Power", "start": "start time", "start2": "Format yyyy MM dd differs from end by up to three months", "end": "End time", "end2": "Format yyyy MM dd differs from star by up to three months", "historyPower30m": "30m average computing power historical record", "historyPower24h": "24-hour average computing power history record", "miningAccount": "Mining account information", "minerData": "Number of miners data", "stateData": "Miner status data", "minerId": "Miner ID", "minerStatus": "Miner status", "minerStatus0": "0 represents online", "minerStatus1": "1 represents offline", "minerStatus2": "2 represents abnormal state", "overviewOfMiners": "Overview of miners under mining accounts", "accountApiKey": "The mining account name under the API-KEY bound account", "allMiners": "All miners under the mining account", "realTimeAccount": "Real time computing power of mining accounts", "account24h": "24-hour average computing power of mining account history", "account24h30m": "Mining account's computing power in the past 24 hours (average computing power of 30m)", "average24h30m": "The average computing power of 30m in the past 24 hours", "miningMachineInformation": "Mining machine information", "realTimeMiningMachine": "Specify the real-time computing power of the mining machine", "aCertainMiner": "The corresponding miner account under the mining account", "miningMachineHistory24h": "Specify the average computing power of the mining machine in the past 24 hours", "realTimeMiningMachine24h30m": "Designated mining machine's computing power in the past 24 hours (average computing power of 30m)",
|
"overviewOfMiningPool": "Overview of Mining Pool", "jurisdiction": "Required permissions", "parameter": "Request parameters", "currency": "currency", "response": "Response parameters", "serviceCharge": "Mining pool handling fee", "minimumPaymentAmount": "Minimum payment amount", "latelyPower24h": "Last seven days' computing power (24-hour average)", "Power24h": "Latest computing power of mining pool (24-hour average)", "height": "The current height of the mining pool", "currentMiners": "The current number of miners in the mining pool", "eachState": "Number of miners in each state", "realTimePower": "Real time computing power of mining pool", "averagePower30m": "Current average computing power of 30m", "averagePower24h": "Current 24-hour average computing power", "Company": "Company", "historyPower": "Overview of Mining Pool Historical Computing Power", "start": "start time", "start2": "Format yyyy MM dd differs from end by up to three months", "end": "End time", "end2": "Format yyyy MM dd differs from star by up to three months", "historyPower30m": "30m average computing power historical record", "historyPower24h": "24-hour average computing power history record", "miningAccount": "Mining account information", "minerData": "Number of miners data", "stateData": "Miner status data", "minerId": "Miner ID", "minerStatus": "Miner status", "minerStatus0": "0 represents online", "minerStatus1": "1 represents offline", "minerStatus2": "2 represents abnormal state", "overviewOfMiners": "Overview of miners under mining accounts", "accountApiKey": "The mining account name under the API-KEY bound account", "allMiners": "All miners under the mining account", "realTimeAccount": "Real time computing power of mining accounts", "account24h": "24-hour average computing power of mining account history", "account24h30m": "Mining account's computing power in the past 24 hours (average computing power of 30m)", "average24h30m": "The average computing power of 30m in the past 24 hours", "miningMachineInformation": "Mining machine information", "realTimeMiningMachine": "Specify the real-time computing power of the mining machine", "aCertainMiner": "The corresponding miner account under the mining account", "miningMachineHistory24h": "Specify the average computing power of the mining machine in the past 24 hours", "realTimeMiningMachine24h30m": "Designated mining machine's computing power in the past 24 hours (average computing power of 30m)",
|
||||||
apiAuthentication5:"API page",
|
apiAuthentication5:"API page",
|
||||||
apiAuthentication6:"Obtain (When requesting tokens, you can check the permissions according to your needs, and the optional permissions are public mining pool data query interface call permission, mining account data query interface call permission, and mining machine data query interface call permission).",
|
apiAuthentication6:"Obtain (When requesting tokens, you can check the permissions according to your needs, and the optional permissions are public mining pool data query interface call permission, mining account data query interface call permission, and mining machine data query interface call permission).",
|
||||||
backMenu:"Return to Table of Contents",
|
|
||||||
catalogue:"Catalogue:",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,351 +0,0 @@
|
|||||||
export const backendSystem_zh = {
|
|
||||||
backendSystem: {
|
|
||||||
title: "后台管理系统",
|
|
||||||
broadcast: "广播",
|
|
||||||
userManagement: "用户管理",
|
|
||||||
workOrder: "工单管理",
|
|
||||||
workOrderRecord: "工单记录",
|
|
||||||
userComputingPower: "用户算力",
|
|
||||||
addBroadcast: "新增广播",
|
|
||||||
editBroadcast: "修 改",
|
|
||||||
publishedBroadcast: "已发布广播",
|
|
||||||
createTime: "创建时间",
|
|
||||||
content: "内容",
|
|
||||||
createUser: "创建人",
|
|
||||||
updateTime: "修改时间",
|
|
||||||
updateUser: "修改人",
|
|
||||||
operation: "操作",
|
|
||||||
edit: "编辑",
|
|
||||||
exceedingInput:"超出输入最大限制",
|
|
||||||
deleteRemind:"确定删除该广播吗?",
|
|
||||||
deleteSuccess:"删除成功",
|
|
||||||
editSuccess:"修改成功",
|
|
||||||
addSuccess:"发布成功",
|
|
||||||
cancel:"取 消",
|
|
||||||
publish:"发 布",
|
|
||||||
logout:"退出",
|
|
||||||
editContent:"修改广播内容",
|
|
||||||
dialogTitle:"新增广播内容",
|
|
||||||
pleaseInputContent:"请输入广播内容",
|
|
||||||
pleaseInputContent2:"请输入内容",
|
|
||||||
newlineInvalid:"广播内容输入换行符无效",
|
|
||||||
onlineUserNum:"在线数量",
|
|
||||||
offlineUserNum:"离线数量",
|
|
||||||
userPower:"用户算力",
|
|
||||||
chartTitle:"用户算力及在离线状态图",
|
|
||||||
noData:"无数据",
|
|
||||||
startDate:"开始日期",
|
|
||||||
endDate:"结束日期",
|
|
||||||
to:"至",
|
|
||||||
userDetails:"用户详情",
|
|
||||||
return:"返回",
|
|
||||||
coin:"币种:",
|
|
||||||
user:"挖矿账户:",
|
|
||||||
amount:"交易金额:",
|
|
||||||
createDate:"收益分配日期",
|
|
||||||
maxHeight:"最大高度",
|
|
||||||
shouldOutDate:"实际转账日期",
|
|
||||||
address:"转账地址",
|
|
||||||
historyAddress:"历史支付地址:",
|
|
||||||
|
|
||||||
userManagementTitle:"注册用户管理",
|
|
||||||
pleaseInput:"请输入",
|
|
||||||
email:"邮箱:",
|
|
||||||
email2:"邮箱",
|
|
||||||
query:"查询",
|
|
||||||
coin2:"币种",
|
|
||||||
amount2:"最小起付金额",
|
|
||||||
status2:"用户状态",
|
|
||||||
minerUser2:"挖矿账号",
|
|
||||||
balance2:"支付地址",
|
|
||||||
active2:"是否自动提现",
|
|
||||||
normal:"正常",
|
|
||||||
delete:"删除",
|
|
||||||
yes:"是",
|
|
||||||
no:"否",
|
|
||||||
Details:"详情",
|
|
||||||
sendEmail:"发送邮件",
|
|
||||||
sendSuccess:"发送成功",
|
|
||||||
sendFail:"发送失败",
|
|
||||||
sendRemind:"确定发送邮件吗?",
|
|
||||||
recipient:"收件人",
|
|
||||||
subject:"邮件主题",
|
|
||||||
text:"邮件内容",
|
|
||||||
send:"发送",
|
|
||||||
emailRemind:"可输入多个邮箱,用逗号隔开",
|
|
||||||
pleaseInputCorrectEmail:"请输入正确的邮箱地址",
|
|
||||||
pleaseInputSubject:"请输入邮件主题",
|
|
||||||
pleaseInputText:"请输入邮件内容",
|
|
||||||
pleaseInputCorrectEmail2:"请输入正确的邮箱地址,多个邮箱用逗号分隔",
|
|
||||||
existDuplicateEmail:"存在重复邮箱,请检查",
|
|
||||||
pleaseInputQueryConditions:"请输入查询条件(挖矿账号、邮箱)",
|
|
||||||
emailContent:"邮件内容",
|
|
||||||
leftNavigation:"选择左侧导航栏查看页面",
|
|
||||||
broadcastPause:"广播已暂停,移开鼠标继续滚动",
|
|
||||||
broadcastResume:"鼠标悬停可暂停滚动",
|
|
||||||
transactionAmount:"交易金额",
|
|
||||||
walletBalance:"钱包余额",
|
|
||||||
bthContent:"广播按钮内容(输入多个按钮,用逗号隔开):",
|
|
||||||
bthContent2:"广播按钮内容",
|
|
||||||
bthPath:"按钮对应跳转页面路径(根据按钮数量顺序输入):",
|
|
||||||
bthPath2:"按钮对应跳转页面路径",
|
|
||||||
broadcastContent:"广播内容:",
|
|
||||||
bthPathStandard:"跳转路径以逗号分隔,最多5个(例:/reportBlock,/miningAccount,/personalMining,/workOrderRecords,/UserWorkDetails),输入换行符无效",
|
|
||||||
pleaseInputButtonContentAndPath:"请输入广播按钮内容和跳转路径",
|
|
||||||
max5:"跳转路径最多输入5个",
|
|
||||||
invalidPath:"无效的跳转地址",
|
|
||||||
invalidPathSuggestions:"建议使用",
|
|
||||||
pathNumberNotMatch:"按钮数量和路径数量不匹配",
|
|
||||||
documentManagement:"文档管理",
|
|
||||||
addDocument:"新增文档",
|
|
||||||
allocationAmount:"分配金额",
|
|
||||||
transferAmount:"转账金额",
|
|
||||||
updateSuccess:"修改成功",
|
|
||||||
publishArticle:"发布文章",
|
|
||||||
pleaseInputKeyword:"请输入搜索内容",
|
|
||||||
pleaseInputType:"请选择文档类型",
|
|
||||||
pleaseSelect:"请选择",
|
|
||||||
miningTutorial:"挖矿教程",
|
|
||||||
commonProblems:"常见问题",
|
|
||||||
other:"其他",
|
|
||||||
announcementCenter:"公告中心",
|
|
||||||
search:"搜索",
|
|
||||||
recommendContent:"推荐内容",
|
|
||||||
recentActivities:"最近活动",
|
|
||||||
viewMore:"查看更多活动公告",
|
|
||||||
documentType:"文档类型",
|
|
||||||
documentTitle:"文档标题",
|
|
||||||
wangeditor:"wangeditor 富文本文档编辑器",
|
|
||||||
insertAnchor:"插入锚点",
|
|
||||||
previewDocument:"预览文档",
|
|
||||||
saveDocument:"保存文档",
|
|
||||||
publishDocument:"发布文档",
|
|
||||||
reset:"重置",
|
|
||||||
documentConfiguration:"文档配置",
|
|
||||||
navigationTitle:"导航标题",
|
|
||||||
pleaseInputDocumentTitle:"请输入文档标题",
|
|
||||||
pleaseSelectDocumentType:"请选择文档类型",
|
|
||||||
titleImageAddress:"标题图片地址",
|
|
||||||
pleaseInputImageAddress:"请输入图片地址",
|
|
||||||
articleAccessAddress:"文章访问地址",
|
|
||||||
pleaseInputAccessAddress:"请输入访问地址",
|
|
||||||
richTextEditor:"富文本编辑器",
|
|
||||||
documentPreview:"文档预览",
|
|
||||||
printPreview:"打印预览",
|
|
||||||
close:"关闭",
|
|
||||||
noContent:"暂无内容",
|
|
||||||
modifyDocument:"修改文档",
|
|
||||||
contentSaved:"内容已保存到本地,请尽快发布,关闭页面可能丢失内容",
|
|
||||||
|
|
||||||
pleaseInputAnchorName:"请输入锚点名称(不能重复)",
|
|
||||||
anchorNameErrorMessage:"锚点名只能包含字母、数字、下划线和中划线",
|
|
||||||
anchorInserted:"锚点已插入",
|
|
||||||
confirm:"确定",
|
|
||||||
pleaseSelectHeader:"请先选中一个标题(h1~h6)",
|
|
||||||
pleaseInputAnchorID:"请输入锚点ID(不能重复)",
|
|
||||||
titleAnchor:"标题锚点",
|
|
||||||
anchorIDErrorMessage:"ID只能包含字母、数字、下划线和中划线",
|
|
||||||
anchorIDAdded:"锚点ID已添加",
|
|
||||||
contentReset:"内容已重置",
|
|
||||||
selectCurrency:"选择币种",
|
|
||||||
pleaseSelectCurrency2:"添加挖矿教程,请选择币种",
|
|
||||||
pleaseInputTitle:"请输入标题",
|
|
||||||
|
|
||||||
searchResult:"搜索结果",
|
|
||||||
returnSearch:"返回搜索",
|
|
||||||
keyword:"关键词",
|
|
||||||
find:"找到",
|
|
||||||
relatedResults:"条相关结果",
|
|
||||||
documentIcon:"文档图标",
|
|
||||||
preview:"预览",
|
|
||||||
noResult:"未找到相关结果",
|
|
||||||
keyword2:"关键词",
|
|
||||||
noMatch:"没有找到匹配的文档",
|
|
||||||
resetSearch:"重新搜索",
|
|
||||||
type:"类型",
|
|
||||||
pendingPaymentSummary:"待支付汇总",
|
|
||||||
userRelated:"用户相关",
|
|
||||||
allocateHeight:"最后分配高度",
|
|
||||||
needPayAmount:"待支付金额",
|
|
||||||
AllocateTime:"最后分配时间",
|
|
||||||
startPayAmount:"起付额",
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const backendSystem_en = {
|
|
||||||
backendSystem: {
|
|
||||||
title: "Backend System",
|
|
||||||
broadcast: "Broadcast",
|
|
||||||
userManagement: "User Management",
|
|
||||||
workOrder: "Work Order Management",
|
|
||||||
workOrderRecord: "Work Order Record",
|
|
||||||
userComputingPower: "User Computing Power",
|
|
||||||
addBroadcast: "Add Broadcast",
|
|
||||||
editBroadcast: "Modify",
|
|
||||||
publishedBroadcast: "Published Broadcast",
|
|
||||||
createTime: "Create Time",
|
|
||||||
content: "Content",
|
|
||||||
createUser: "Create User",
|
|
||||||
updateTime: "Update Time",
|
|
||||||
updateUser: "Update User",
|
|
||||||
operation: "Operation",
|
|
||||||
edit: "Edit",
|
|
||||||
exceedingInput:"Exceeding Input Maximum Limit",
|
|
||||||
deleteRemind:"Are you sure you want to delete this broadcast?",
|
|
||||||
deleteSuccess:"Delete Success",
|
|
||||||
editSuccess:"Edit Success",
|
|
||||||
addSuccess:"Add Success",
|
|
||||||
cancel:"Cancel",
|
|
||||||
publish:"Publish",
|
|
||||||
logout:"Logout",
|
|
||||||
editContent:"Edit Broadcast Content",
|
|
||||||
dialogTitle:"Add Broadcast Content",
|
|
||||||
pleaseInputContent:"Please input broadcast content",
|
|
||||||
newlineInvalid:"Invalid line break for broadcasting content input",
|
|
||||||
onlineUserNum:"Online Number",
|
|
||||||
offlineUserNum:"Offline Number",
|
|
||||||
userPower:"User Power",
|
|
||||||
chartTitle:"User Power and Online/Offline Status Chart",
|
|
||||||
noData:"No Data",
|
|
||||||
startDate:"Start Date",
|
|
||||||
endDate:"End Date",
|
|
||||||
to:"To",
|
|
||||||
userDetails:"User Details",
|
|
||||||
return:"Return",
|
|
||||||
coin:"Coin:",
|
|
||||||
user:"Mining account:",
|
|
||||||
amount:"Amount:",
|
|
||||||
createDate:"Create Date",
|
|
||||||
maxHeight:"Max Height",
|
|
||||||
shouldOutDate:"Should Out Date",
|
|
||||||
address:"Address",
|
|
||||||
historyAddress:"History Payment Address:",
|
|
||||||
userManagementTitle:"User Management",
|
|
||||||
pleaseInput:"Please Input",
|
|
||||||
email:"Email:",
|
|
||||||
email2:"Email",
|
|
||||||
query:"Query",
|
|
||||||
coin2:"Coin",
|
|
||||||
amount2:"Minimum Payout Amount",
|
|
||||||
status2:"User Status",
|
|
||||||
minerUser2:"Miner User",
|
|
||||||
balance2:"Payment Address",
|
|
||||||
active2:"Automatic Withdrawal",
|
|
||||||
normal:"Normal",
|
|
||||||
delete:"Delete",
|
|
||||||
yes:"Yes",
|
|
||||||
no:"No",
|
|
||||||
Details:"Details",
|
|
||||||
sendEmail:"Send Email",
|
|
||||||
sendSuccess:"Send Success",
|
|
||||||
sendFail:"Send Fail",
|
|
||||||
sendRemind:"Are you sure you want to send an email?",
|
|
||||||
recipient:"Recipient",
|
|
||||||
subject:"Email Subject",
|
|
||||||
text:"Email Content",
|
|
||||||
send:"Send",
|
|
||||||
emailRemind:"Multiple emails can be entered, separated by commas",
|
|
||||||
pleaseInputCorrectEmail:"Please enter a valid email address",
|
|
||||||
pleaseInputSubject:"Please enter an email subject",
|
|
||||||
pleaseInputText:"Please enter an email content",
|
|
||||||
pleaseInputCorrectEmail2:"Please enter a valid email address, multiple emails separated by commas",
|
|
||||||
existDuplicateEmail:"Duplicate email exists, please check",
|
|
||||||
pleaseInputQueryConditions:"Please enter the query conditions (miner account, email)",
|
|
||||||
|
|
||||||
emailContent:"Email Content",
|
|
||||||
leftNavigation:"Select the left navigation bar to view the page",
|
|
||||||
|
|
||||||
broadcastPause:"Broadcast has been paused, move the mouse to continue scrolling",
|
|
||||||
broadcastResume:"Hover to pause scrolling",
|
|
||||||
transactionAmount:"Transaction Amount",
|
|
||||||
walletBalance:"Wallet Balance",
|
|
||||||
bthContent:"Broadcast Button Content:",
|
|
||||||
bthPath:"Button Corresponding Jump Page Path:",
|
|
||||||
broadcastContent:"Broadcast Content:",
|
|
||||||
bthPathStandard:"Jump paths separated by commas, up to 5 (example: /reportBlock,/miningAccount,/personalMining,/workOrderRecords,/UserWorkDetails), invalid for line breaks",
|
|
||||||
pleaseInputButtonContentAndPath:"Please input broadcast button content and jump path",
|
|
||||||
bthContent2:"Broadcast Button Content",
|
|
||||||
bthPath2:"Button Corresponding Jump Page Path",
|
|
||||||
max5:"The number of jump paths is up to 5",
|
|
||||||
invalidPath:"Invalid jump address",
|
|
||||||
invalidPathSuggestions:"Suggested paths",
|
|
||||||
pathNumberNotMatch:"The number of buttons and paths does not match",
|
|
||||||
documentManagement:"Document Management",
|
|
||||||
addDocument:"Add Document",
|
|
||||||
allocationAmount:"Allocation Amount",
|
|
||||||
transferAmount:"Transfer Amount",
|
|
||||||
updateSuccess:"Update Success",
|
|
||||||
publishArticle:"Publish Article",
|
|
||||||
pleaseInputKeyword:"Please input search content",
|
|
||||||
pleaseInputType:"Please select document type",
|
|
||||||
pleaseSelect:"Please select",
|
|
||||||
miningTutorial:"Mining Tutorial",
|
|
||||||
commonProblems:"Common Problems",
|
|
||||||
other:"Other",
|
|
||||||
announcementCenter:"Announcement Center",
|
|
||||||
search:"Search",
|
|
||||||
recommendContent:"Recommend Content",
|
|
||||||
recentActivities:"Recent Activities",
|
|
||||||
viewMore:"View More Activity Announcements",
|
|
||||||
documentType:"Document Type",
|
|
||||||
documentTitle:"Document Title",
|
|
||||||
wangeditor:"wangeditor Rich Text Editor",
|
|
||||||
insertAnchor:"Insert Anchor",
|
|
||||||
previewDocument:"Preview Document",
|
|
||||||
saveDocument:"Save Document",
|
|
||||||
publishDocument:"Publish Document",
|
|
||||||
reset:"Reset",
|
|
||||||
documentConfiguration:"Document Configuration",
|
|
||||||
navigationTitle:"Navigation Title",
|
|
||||||
pleaseInputDocumentTitle:"Please input document title",
|
|
||||||
pleaseSelectDocumentType:"Please select document type",
|
|
||||||
titleImageAddress:"Title Image Address",
|
|
||||||
pleaseInputImageAddress:"Please input image address",
|
|
||||||
articleAccessAddress:"Article Access Address",
|
|
||||||
pleaseInputAccessAddress:"Please input access address",
|
|
||||||
richTextEditor:"Rich Text Editor",
|
|
||||||
documentPreview:"Document Preview",
|
|
||||||
printPreview:"Print Preview",
|
|
||||||
close:"Close",
|
|
||||||
noContent:"No Content",
|
|
||||||
modifyDocument:"Modify Document",
|
|
||||||
contentSaved:"Content has been saved to local, please publish it as soon as possible, the content may be lost if the page is closed",
|
|
||||||
|
|
||||||
pleaseInputAnchorName:"Please input anchor name (cannot be repeated)",
|
|
||||||
anchorNameErrorMessage:"Anchor name can only contain letters, numbers, underscores, and hyphens",
|
|
||||||
anchorInserted:"Anchor inserted",
|
|
||||||
confirm:"Confirm",
|
|
||||||
pleaseSelectHeader:"Please select a title (h1~h6)",
|
|
||||||
pleaseInputAnchorID:"Please input anchor ID (cannot be repeated)",
|
|
||||||
titleAnchor:"Title Anchor",
|
|
||||||
anchorIDErrorMessage:"ID can only contain letters, numbers, underscores, and hyphens",
|
|
||||||
anchorIDAdded:"Anchor ID added",
|
|
||||||
contentReset:"Content has been reset",
|
|
||||||
selectCurrency:"Select Currency",
|
|
||||||
pleaseSelectCurrency2:"Please select a currency when adding mining tutorials",
|
|
||||||
pleaseInputContent2:"Please input content",
|
|
||||||
pleaseInputTitle:"Please input title",
|
|
||||||
searchResult:"Search Result",
|
|
||||||
returnSearch:"Return Search",
|
|
||||||
keyword:"Keyword",
|
|
||||||
find:"Find",
|
|
||||||
relatedResults:"Items",
|
|
||||||
documentIcon:"Document Icon",
|
|
||||||
preview:"Preview",
|
|
||||||
noResult:"No Related Results",
|
|
||||||
keyword2:"Keyword",
|
|
||||||
noMatch:"No Matching Document",
|
|
||||||
resetSearch:"Reset Search",
|
|
||||||
type:"Type",
|
|
||||||
|
|
||||||
pendingPaymentSummary:"Pending Payment",
|
|
||||||
userRelated:"User Related",
|
|
||||||
allocateHeight:"Allocate Height",
|
|
||||||
needPayAmount:"Need Pay Amount",
|
|
||||||
AllocateTime:"Should Out Date",
|
|
||||||
startPayAmount:"Start Pay Amount",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -78,19 +78,7 @@ export const home_zh = {
|
|||||||
view:"详情",
|
view:"详情",
|
||||||
describe:"奖励分配:1天/次,每日0时(utc+0), 转账:1天/次,每日4时(utc+0)起,具体取决于区块成熟条件",
|
describe:"奖励分配:1天/次,每日0时(utc+0), 转账:1天/次,每日4时(utc+0)起,具体取决于区块成熟条件",
|
||||||
networkReconnected:"网络已重新连接,正在恢复数据...",
|
networkReconnected:"网络已重新连接,正在恢复数据...",
|
||||||
networkOffline:"网络连接已断开,系统将在恢复连接后自动重试",
|
networkOffline:"网络连接已断开,系统将在恢复连接后自动重试"
|
||||||
helpCenter:"帮助中心",
|
|
||||||
announcements:"公告中心",
|
|
||||||
latestTitle:"最新公告",
|
|
||||||
noData:"暂无公告",
|
|
||||||
viewAll:"查看所有",
|
|
||||||
articles:"篇文章",
|
|
||||||
allocationExplanation:"矿池分配及转账规则",
|
|
||||||
loadingContent:"正在加载内容...",
|
|
||||||
noContent:"暂无内容",
|
|
||||||
unknownType:"未知类型",
|
|
||||||
other:"其他",
|
|
||||||
machineLease:"矿机租赁",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,19 +162,6 @@ export const home_en = {
|
|||||||
view:"Details",
|
view:"Details",
|
||||||
describe:"Reward distribution: 1 day/times, daily at 0:00 (utc+0), transfer: 1 day/times, daily from 4:00 (utc+0), depending on block maturity conditions ",
|
describe:"Reward distribution: 1 day/times, daily at 0:00 (utc+0), transfer: 1 day/times, daily from 4:00 (utc+0), depending on block maturity conditions ",
|
||||||
networkReconnected:"Network has been reconnected, recovering data...",
|
networkReconnected:"Network has been reconnected, recovering data...",
|
||||||
networkOffline:"Network connection has been disconnected, the system will automatically retry after recovery",
|
networkOffline:"Network connection has been disconnected, the system will automatically retry after recovery"
|
||||||
helpCenter:"Help Center",
|
|
||||||
announcements:"Announcements",
|
|
||||||
latestTitle:"Latest Announcements",
|
|
||||||
noData:"No data",
|
|
||||||
viewAll:"View all",
|
|
||||||
articles:" articles",
|
|
||||||
allocationExplanation:"Pool allocation and transfer rules",
|
|
||||||
loadingContent:"Loading content...",
|
|
||||||
noContent:"No content",
|
|
||||||
unknownType:"Unknown Type",
|
|
||||||
other:"Other",
|
|
||||||
machineLease:"Machine Lease",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,6 @@ import {workOrder_zh,workOrder_en} from'./submitWorkOrder'
|
|||||||
import {alerts_zh,alerts_en} from'./alerts'
|
import {alerts_zh,alerts_en} from'./alerts'
|
||||||
import {seo_zh,seo_en} from'./seo'
|
import {seo_zh,seo_en} from'./seo'
|
||||||
import {chooseUs_zh,chooseUs_en} from'./dataDisplay'
|
import {chooseUs_zh,chooseUs_en} from'./dataDisplay'
|
||||||
import {ChatWidget_zh,ChatWidget_en} from'./ChatWidget'
|
|
||||||
import {backendSystem_zh,backendSystem_en} from'./backendSystem'
|
|
||||||
import {announcements_zh,announcements_en} from'./announcements'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -34,9 +30,7 @@ export default {
|
|||||||
...alerts_zh,
|
...alerts_zh,
|
||||||
...seo_zh,
|
...seo_zh,
|
||||||
...chooseUs_zh,
|
...chooseUs_zh,
|
||||||
...ChatWidget_zh,
|
|
||||||
...backendSystem_zh,
|
|
||||||
...announcements_zh,
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -56,9 +50,7 @@ export default {
|
|||||||
...alerts_en,
|
...alerts_en,
|
||||||
...seo_en,
|
...seo_en,
|
||||||
...chooseUs_en,
|
...chooseUs_en,
|
||||||
...ChatWidget_en,
|
|
||||||
...backendSystem_en,
|
|
||||||
...announcements_en,
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -134,9 +134,6 @@ export const personalCenter_zh = {
|
|||||||
ipFormat:"请检查IP地址格式是否正确",
|
ipFormat:"请检查IP地址格式是否正确",
|
||||||
screen:"筛选币种",
|
screen:"筛选币种",
|
||||||
workOrderRecord:"工单记录",
|
workOrderRecord:"工单记录",
|
||||||
deleteAccountWarning:"删除后关于此账户的相关信息将不能恢复,请慎重操作!",
|
|
||||||
deleteAccountSuccess:"账户删除成功",
|
|
||||||
deleteAccountVerificationRequired:"删除账户信息为敏感操作,为保护您的账户安全,请先开启双重验证后再删除",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,8 +243,5 @@ export const personalCenter_en = {
|
|||||||
ipFormat:"Please check if the IP address format is correct",
|
ipFormat:"Please check if the IP address format is correct",
|
||||||
screen:"Filter currencies",
|
screen:"Filter currencies",
|
||||||
workOrderRecord:"Work order record",
|
workOrderRecord:"Work order record",
|
||||||
deleteAccountWarning:"After deletion, the relevant information about this account cannot be restored. Please proceed with caution!",
|
|
||||||
deleteAccountSuccess:"Account deleted successfully",
|
|
||||||
deleteAccountVerificationRequired:"Deleting account information is a sensitive operation. To protect your account security, please enable dual verification before deleting.",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,13 +29,6 @@ export const seo_zh = {
|
|||||||
allocationExplanation: "M2Pool 矿池分配及转账说明页面,详细介绍各币种的成熟条件、出块间隔及预估时间,何时将挖矿收益分配及转账至用户账户,提供用户清晰的了解分配及转账指南。",
|
allocationExplanation: "M2Pool 矿池分配及转账说明页面,详细介绍各币种的成熟条件、出块间隔及预估时间,何时将挖矿收益分配及转账至用户账户,提供用户清晰的了解分配及转账指南。",
|
||||||
enxAccess: "Entropyx(enx) 接入页面,详细介绍如何接入 M2Pool 矿池进行 enx 币种挖矿,提供用户便捷的接入指南,轻松开启挖矿之旅。",
|
enxAccess: "Entropyx(enx) 接入页面,详细介绍如何接入 M2Pool 矿池进行 enx 币种挖矿,提供用户便捷的接入指南,轻松开启挖矿之旅。",
|
||||||
alphAccess: "Alephium(alph) 接入页面,详细介绍如何接入 M2Pool 矿池进行 Alephium(alph) 币种挖矿,提供用户便捷的接入指南,轻松开启挖矿之旅。",
|
alphAccess: "Alephium(alph) 接入页面,详细介绍如何接入 M2Pool 矿池进行 Alephium(alph) 币种挖矿,提供用户便捷的接入指南,轻松开启挖矿之旅。",
|
||||||
broadcast: "M2Pool 矿池广播页面,管理员可在此查看已发布的广播信息,包括广播内容、发布时间、发布者等。",
|
|
||||||
userManagement: "M2Pool 矿池用户管理页面,管理员可在此查看所有用户信息,包括用户名、邮箱、注册时间、登录时间等。",
|
|
||||||
helpCenter:"M2Pool 矿池帮助中心页面,提供用户全面的帮助中心信息,包括新手入门、矿业数据、常见问题、公告中心、其他等。",
|
|
||||||
announcements:"M2Pool 矿池公告中心页面,提供最新的矿池公告、系统通知、服务更新和重要信息,让用户及时了解矿池动态和政策变更。",
|
|
||||||
documentManagement:"M2Pool 矿池文档管理页面,提供最新的文档信息,让用户及时了解文档信息。",
|
|
||||||
pendingPaymentSummary:"M2Pool 矿池待支付汇总页面,提供最新的待支付汇总信息,及时了解用户待支付汇总信息。",
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,12 +53,5 @@ export const seo_en = {
|
|||||||
allocationExplanation: "The M2Pool mining pool allocation and transfer instructions page provides detailed information on the maturity conditions, block interval, and estimated time of each currency, as well as when to allocate and transfer mining profits to user accounts, providing users with a clear understanding of allocation and transfer guidelines.",
|
allocationExplanation: "The M2Pool mining pool allocation and transfer instructions page provides detailed information on the maturity conditions, block interval, and estimated time of each currency, as well as when to allocate and transfer mining profits to user accounts, providing users with a clear understanding of allocation and transfer guidelines.",
|
||||||
enxAccess: "Entropyx (enx) access page provides detailed instructions on how to access the M2Pool mining pool for enx currency mining, offering users a convenient access guide to easily start their mining journey.",
|
enxAccess: "Entropyx (enx) access page provides detailed instructions on how to access the M2Pool mining pool for enx currency mining, offering users a convenient access guide to easily start their mining journey.",
|
||||||
alphAccess: "The M2Pool Alephium(alph) access page provides detailed instructions on how to access the M2Pool mining pool for Alephium(alph) currency mining, offering users a convenient access guide to easily start their mining journey.",
|
alphAccess: "The M2Pool Alephium(alph) access page provides detailed instructions on how to access the M2Pool mining pool for Alephium(alph) currency mining, offering users a convenient access guide to easily start their mining journey.",
|
||||||
broadcast: "M2Pool mining pool broadcast page, where administrators can view published broadcast information, including broadcast content, release time, publisher, etc.",
|
|
||||||
userManagement: "M2Pool mining pool user management page, where administrators can view all user information, including user name, email, registration time, login time, etc.",
|
|
||||||
helpCenter:"M2Pool mining pool help center page, providing users with comprehensive help center information, including beginner's guide, mining data, frequently asked questions, announcement center, and other information.",
|
|
||||||
announcements:"M2Pool mining pool announcement center page, providing the latest mining pool announcements, system notifications, service updates and important information, allowing users to stay informed of mining pool dynamics and policy changes.",
|
|
||||||
documentManagement:"M2Pool mining pool document management page, providing the latest document information, allowing users to stay informed of document information.",
|
|
||||||
pendingPaymentSummary:"M2Pool mining pool pending payment summary page, providing the latest pending payment summary information, allowing users to stay informed of pending payment summary information.",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,32 +42,6 @@ export const userLang_zh = {
|
|||||||
modifiedSuccessfully:"密码修改成功,请登录",
|
modifiedSuccessfully:"密码修改成功,请登录",
|
||||||
verificationEnabled:"已开启验证",
|
verificationEnabled:"已开启验证",
|
||||||
newPassword2:"新密码",
|
newPassword2:"新密码",
|
||||||
},
|
|
||||||
// 密码错误详细提示
|
|
||||||
passwordError: {
|
|
||||||
tooShort: "密码长度不足8位",
|
|
||||||
tooLong: "密码长度超过32位",
|
|
||||||
containsChinese: "密码不能包含中文字符",
|
|
||||||
noLowercase: "密码必须包含小写字母(a-z)",
|
|
||||||
noUppercase: "密码必须包含大写字母(A-Z)",
|
|
||||||
noNumber: "密码必须包含数字(0-9)",
|
|
||||||
noSpecialChar: "密码必须包含特殊字符,可用字符: ! @ # $ % ^ & * ( ) _ + - = [ ] { } | ; : ' \" , . < > ? / \\ ` ~",
|
|
||||||
},
|
|
||||||
// 密码强度等级
|
|
||||||
passwordStrength: {
|
|
||||||
none: "请输入密码",
|
|
||||||
weak: "密码强度:弱",
|
|
||||||
medium: "密码强度:中等",
|
|
||||||
strong: "密码强度:强"
|
|
||||||
},
|
|
||||||
// 密码规则提示(用于✓✗列表)
|
|
||||||
passwordRules: {
|
|
||||||
length: "长度为8-32位",
|
|
||||||
noChinese: "不包含中文字符",
|
|
||||||
lowercase: "包含小写字母",
|
|
||||||
uppercase: "包含大写字母",
|
|
||||||
number: "包含数字",
|
|
||||||
specialChar: "包含特殊字符"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,31 +89,5 @@ export const userLang_en = {
|
|||||||
modifiedSuccessfully:"Password changed successfully, please log in",
|
modifiedSuccessfully:"Password changed successfully, please log in",
|
||||||
verificationEnabled:"Verification enabled",
|
verificationEnabled:"Verification enabled",
|
||||||
newPassword2:"New Password",
|
newPassword2:"New Password",
|
||||||
},
|
|
||||||
// Detailed password error messages
|
|
||||||
passwordError: {
|
|
||||||
tooShort: "Password must be at least 8 characters",
|
|
||||||
tooLong: "Password cannot exceed 32 characters",
|
|
||||||
containsChinese: "Password cannot contain Chinese characters",
|
|
||||||
noLowercase: "Password must contain lowercase letters (a-z)",
|
|
||||||
noUppercase: "Password must contain uppercase letters (A-Z)",
|
|
||||||
noNumber: "Password must contain numbers (0-9)",
|
|
||||||
noSpecialChar: "Password must contain special characters. Allowed: ! @ # $ % ^ & * ( ) _ + - = [ ] { } | ; : ' \" , . < > ? / \\ ` ~",
|
|
||||||
},
|
|
||||||
// Password strength levels
|
|
||||||
passwordStrength: {
|
|
||||||
none: "Please enter password",
|
|
||||||
weak: "Password Strength: Weak",
|
|
||||||
medium: "Password Strength: Medium",
|
|
||||||
strong: "Password Strength: Strong"
|
|
||||||
},
|
|
||||||
// Password rules checklist
|
|
||||||
passwordRules: {
|
|
||||||
length: "8-32 characters",
|
|
||||||
noChinese: "No Chinese characters",
|
|
||||||
lowercase: "Contains lowercase letter",
|
|
||||||
uppercase: "Contains uppercase letter",
|
|
||||||
number: "Contains number",
|
|
||||||
specialChar: "Contains special character"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<el-container style="width: 100vw;height: 100vh;" class="containerApp" >
|
||||||
<BackAdminLayout v-if="jurisdiction && jurisdiction.roleKey === 'back_admin'"> </BackAdminLayout>
|
|
||||||
<el-container v-else style="width: 100vw;height: 100vh;" class="containerApp" >
|
|
||||||
<el-header class="el-header" >
|
<el-header class="el-header" >
|
||||||
<MoveHead v-if="$isMobile"></MoveHead>
|
<MoveHead v-if="$isMobile"></MoveHead>
|
||||||
<comHeard v-else></comHeard>
|
<comHeard v-else></comHeard>
|
||||||
</el-header>
|
</el-header>
|
||||||
<el-main class="el-main">
|
<el-main>
|
||||||
<appMain></appMain>
|
<appMain></appMain>
|
||||||
</el-main>
|
</el-main>
|
||||||
|
|
||||||
</el-container>
|
</el-container>
|
||||||
|
|
||||||
|
|
||||||
@@ -20,35 +19,8 @@ export default {
|
|||||||
comHeard: () => import("../components/header.vue"),
|
comHeard: () => import("../components/header.vue"),
|
||||||
appMain: () => import("../components/content.vue"),
|
appMain: () => import("../components/content.vue"),
|
||||||
MoveHead: () => import("../components/MoveHead.vue"),
|
MoveHead: () => import("../components/MoveHead.vue"),
|
||||||
BackAdminLayout: () => import("../components/BackAdminLayout.vue"),
|
|
||||||
},
|
|
||||||
data(){
|
|
||||||
return {
|
|
||||||
jurisdiction: {
|
|
||||||
roleKey: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
|
|
||||||
window.addEventListener("setItem", () => {
|
},
|
||||||
let jurisdiction = localStorage.getItem("jurisdiction");
|
|
||||||
try {
|
|
||||||
jurisdiction = jurisdiction ? JSON.parse(jurisdiction) : { roleKey: "" };
|
|
||||||
} catch (e) {
|
|
||||||
jurisdiction = { roleKey: "" };
|
|
||||||
}
|
|
||||||
this.jurisdiction = jurisdiction;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,14 +11,6 @@ import './assets/icons/iconfont/iconfont.css'
|
|||||||
import {$addStorageEvent} from '../src/utils/publicMethods'
|
import {$addStorageEvent} from '../src/utils/publicMethods'
|
||||||
import MetaInfo from 'vue-meta-info'
|
import MetaInfo from 'vue-meta-info'
|
||||||
import loadingStateMixin from './utils/loadingStateMixin';
|
import loadingStateMixin from './utils/loadingStateMixin';
|
||||||
import networkRecoveryMixin from './mixins/networkRecoveryMixin';
|
|
||||||
import './utils/loadingRecovery';
|
|
||||||
import errorNotificationManager from '../src/utils/errorNotificationManager';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 创建事件总线 用于组件通信
|
|
||||||
Vue.prototype.$bus = new Vue();
|
|
||||||
|
|
||||||
Vue.use(MetaInfo)
|
Vue.use(MetaInfo)
|
||||||
Vue.prototype.$addStorageEvent = $addStorageEvent // 添加storage事件
|
Vue.prototype.$addStorageEvent = $addStorageEvent // 添加storage事件
|
||||||
@@ -29,32 +21,13 @@ Vue.use(ElementUI, {
|
|||||||
Vue.prototype.$axios = axios
|
Vue.prototype.$axios = axios
|
||||||
|
|
||||||
console.log = ()=>{} //全局关闭打印
|
console.log = ()=>{} //全局关闭打印
|
||||||
// 全局注册混入
|
Vue.mixin(loadingStateMixin);
|
||||||
Vue.mixin(loadingStateMixin);//loading状态管理
|
|
||||||
Vue.mixin(networkRecoveryMixin);//网络恢复后数据刷新
|
|
||||||
|
|
||||||
Vue.prototype.$baseApi = process.env.VUE_APP_BASE_URL //图片base路径
|
Vue.prototype.$baseApi = process.env.VUE_APP_BASE_URL //图片base路径
|
||||||
const screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
const screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||||
const isNarrowScreen = screenWidth < 1280;
|
const isNarrowScreen = screenWidth < 1280;
|
||||||
Vue.prototype.$isMobile = isNarrowScreen
|
Vue.prototype.$isMobile = isNarrowScreen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局处理未捕获的 Promise 拒绝(仅限网络类错误),
|
|
||||||
* 防止错误遮罩层把页面完全遮挡。不影响其他错误的默认行为。
|
|
||||||
*/
|
|
||||||
window.addEventListener('unhandledrejection', (event) => {
|
|
||||||
const reason = event && event.reason;
|
|
||||||
const message = typeof reason === 'string' ? reason : (reason && reason.message);
|
|
||||||
if (message && (message === 'Network Error' || message.includes('timeout'))) {
|
|
||||||
event.preventDefault();
|
|
||||||
console.warn('[unhandledrejection] blocked network error:', message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 在路由守卫中设置
|
// 在路由守卫中设置
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
// 从路由中获取语言参数
|
// 从路由中获取语言参数
|
||||||
@@ -67,21 +40,11 @@ router.beforeEach((to, from, next) => {
|
|||||||
if (i18n.locale !== lang) {
|
if (i18n.locale !== lang) {
|
||||||
i18n.locale = lang;
|
i18n.locale = lang;
|
||||||
}
|
}
|
||||||
const token = localStorage.getItem('token');
|
|
||||||
if (!token || token === 'null') {
|
|
||||||
// 通知断开所有客服连接
|
|
||||||
localStorage.setItem('cs_disconnect_all', Date.now().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 定期清理过期的错误记录
|
|
||||||
setInterval(() => {
|
|
||||||
errorNotificationManager.cleanup();
|
|
||||||
}, 60000); // 每分钟清理一次
|
|
||||||
|
|
||||||
window.vm = new Vue({
|
window.vm = new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
//处理断网重连后数据刷新的混入
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
// 注册需要在网络恢复时调用的方法名
|
|
||||||
recoveryMethods: [],
|
|
||||||
// 上次调用这些方法时的参数
|
|
||||||
methodParams: {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 注册需要在网络恢复时自动重新调用的方法
|
|
||||||
* @param {String} methodName - 方法名
|
|
||||||
* @param {*} params - 调用方法时需要的参数
|
|
||||||
*/
|
|
||||||
registerRecoveryMethod(methodName, params) {
|
|
||||||
if (typeof this[methodName] === 'function' && !this.recoveryMethods.includes(methodName)) {
|
|
||||||
this.recoveryMethods.push(methodName);
|
|
||||||
this.methodParams[methodName] = params;
|
|
||||||
console.log(`[NetworkRecovery] 注册方法: ${methodName}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新方法的参数
|
|
||||||
* @param {String} methodName - 方法名
|
|
||||||
* @param {*} params - 新的参数
|
|
||||||
*/
|
|
||||||
updateMethodParams(methodName, params) {
|
|
||||||
if (this.recoveryMethods.includes(methodName)) {
|
|
||||||
this.methodParams[methodName] = params;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网络恢复后调用所有注册的方法
|
|
||||||
*/
|
|
||||||
handleNetworkRecovery() {
|
|
||||||
console.log('[NetworkRecovery] 网络已恢复,正在刷新数据...');
|
|
||||||
this.recoveryMethods.forEach(methodName => {
|
|
||||||
if (typeof this[methodName] === 'function') {
|
|
||||||
const params = this.methodParams[methodName];
|
|
||||||
console.log(`[NetworkRecovery] 重新调用方法: ${methodName}`);
|
|
||||||
this[methodName](params);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
// 监听网络恢复事件
|
|
||||||
window.addEventListener('network-retry-complete', this.handleNetworkRecovery);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
// 清理事件监听
|
|
||||||
window.removeEventListener('network-retry-complete', this.handleNetworkRecovery);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -30,10 +30,9 @@ const childrenRoutes = [
|
|||||||
path: 'miningAccount',
|
path: 'miningAccount',
|
||||||
name: 'MiningAccount',
|
name: 'MiningAccount',
|
||||||
component: () => import('../views/miningAccount/index.vue'),
|
component: () => import('../views/miningAccount/index.vue'),
|
||||||
meta: {
|
meta: {title: '挖矿账户页面',
|
||||||
title: '挖矿账户页面',
|
|
||||||
description:i18n.t(`seo.miningAccount`),
|
description:i18n.t(`seo.miningAccount`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool mining account, crypto mining stats, mining rewards, hashrate monitor, 矿池账户, 挖矿收益, 算力监控'
|
// keywords: 'M2Pool mining account, crypto mining stats, mining rewards, hashrate monitor, 矿池账户, 挖矿收益, 算力监控'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'M2Pool mining account, crypto mining stats, mining rewards, hashrate monitor, 矿池账户, 挖矿收益, 算力监控',
|
en: 'M2Pool mining account, crypto mining stats, mining rewards, hashrate monitor, 矿池账户, 挖矿收益, 算力监控',
|
||||||
@@ -45,8 +44,7 @@ const childrenRoutes = [
|
|||||||
path: 'readOnlyDisplay',
|
path: 'readOnlyDisplay',
|
||||||
name: 'ReadOnlyDisplay',
|
name: 'ReadOnlyDisplay',
|
||||||
component: () => import('../views/readOnlyDisplay/index.vue'),
|
component: () => import('../views/readOnlyDisplay/index.vue'),
|
||||||
meta: {
|
meta: {title: '只读页面展示页',
|
||||||
title: '只读页面展示页',
|
|
||||||
description:i18n.t(`seo.readOnlyDisplay`),
|
description:i18n.t(`seo.readOnlyDisplay`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,只读页面,收益状况,矿工信息,Read only page,Revenue situation,Mining Pool,Miner information'
|
// keywords: 'M2Pool 矿池,只读页面,收益状况,矿工信息,Read only page,Revenue situation,Mining Pool,Miner information'
|
||||||
@@ -63,10 +61,9 @@ const childrenRoutes = [
|
|||||||
path: 'reportBlock',
|
path: 'reportBlock',
|
||||||
name: 'ReportBlock',
|
name: 'ReportBlock',
|
||||||
component: () => import('../views/reportBlock/index.vue'),
|
component: () => import('../views/reportBlock/index.vue'),
|
||||||
meta: {
|
meta: {title: '报块页面',
|
||||||
title: '报块页面',
|
|
||||||
description:i18n.t(`seo.reportBlock`),
|
description:i18n.t(`seo.reportBlock`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,报块页面,幸运值,区块高度,Block page,Lucky Value,block height,Mining Pool'
|
// keywords: 'M2Pool 矿池,报块页面,幸运值,区块高度,Block page,Lucky Value,block height,Mining Pool'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Block page,Lucky Value,block height,Mining Pool',
|
en: 'Block page,Lucky Value,block height,Mining Pool',
|
||||||
@@ -76,147 +73,11 @@ const childrenRoutes = [
|
|||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{//帮助中心
|
|
||||||
path: 'helpCenter',
|
|
||||||
name: 'HelpCenter',
|
|
||||||
component: () => import('../views/helpCenter/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '帮助中心',
|
|
||||||
description: i18n.t(`seo.helpCenter`),
|
|
||||||
allAuthority: [`all`],
|
|
||||||
keywords: {
|
|
||||||
en: 'Help Center,Beginner Guide,Mining Data,Frequently Asked Questions,Announcement Center,Other',
|
|
||||||
zh: '帮助中心,新手入门,常见问题,公告中心'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//编辑器测试
|
|
||||||
path: 'editorDocument',
|
|
||||||
name: 'EditorDocument',
|
|
||||||
component: () => import('../views/editorDocument.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '编辑器测试',
|
|
||||||
description: i18n.t(`seo.helpCenter`),
|
|
||||||
allAuthority: [`all`],
|
|
||||||
keywords: {
|
|
||||||
en: 'Help Center,Beginner Guide,Mining Data,Frequently Asked Questions,Announcement Center,Other',
|
|
||||||
zh: '帮助中心,新手入门,常见问题,公告中心'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{//广播页面
|
|
||||||
path: 'broadcast',
|
|
||||||
name: 'Broadcast',
|
|
||||||
component: () => import('../views/broadcast/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '广播页面',
|
|
||||||
description: i18n.t(`seo.broadcast`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'broadcast',
|
|
||||||
zh: '广播'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//用户管理
|
|
||||||
path: 'userManagement',
|
|
||||||
name: 'UserManagement',
|
|
||||||
component: () => import('../views/userManagement/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '用户管理',
|
|
||||||
description: i18n.t(`seo.userManagement`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'userManagement',
|
|
||||||
zh: '用户管理'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
{//用户详情
|
|
||||||
path: 'userDetails',
|
|
||||||
name: 'UserDetails',
|
|
||||||
component: () => import('../views/userDetails/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '用户详情',
|
|
||||||
description: i18n.t(`seo.userManagement`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'userDetails',
|
|
||||||
zh: '用户详情'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//待支付汇总
|
|
||||||
path: 'pendingPaymentSummary',
|
|
||||||
name: 'PendingPaymentSummary',
|
|
||||||
component: () => import('../views/pendingPaymentSummary/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '待支付汇总',
|
|
||||||
description: i18n.t(`seo.pendingPaymentSummary`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'pendingPaymentSummary',
|
|
||||||
zh: '待支付汇总'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
{//文档管理
|
|
||||||
path: 'documentManagement',
|
|
||||||
name: 'DocumentManagement',
|
|
||||||
component: () => import('../views/documentManagement/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '文档管理',
|
|
||||||
description: i18n.t(`seo.documentManagement`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'documentManagement',
|
|
||||||
zh: '文档管理'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//新增文档 modifyDocument
|
|
||||||
path: 'addDocument',
|
|
||||||
name: 'AddDocument',
|
|
||||||
component: () => import('../views/documentManagement/addDocument/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '新增文档',
|
|
||||||
description: i18n.t(`seo.documentManagement`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'documentManagement',
|
|
||||||
zh: '文档管理'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//修改文档
|
|
||||||
path: 'modifyDocument',
|
|
||||||
name: 'ModifyDocument',
|
|
||||||
component: () => import('../views/documentManagement/modifyDocument/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '修改文档',
|
|
||||||
description: i18n.t(`seo.documentManagement`),
|
|
||||||
allAuthority: [`back_admin`],
|
|
||||||
keywords: {
|
|
||||||
en: 'documentManagement',
|
|
||||||
zh: '文档管理'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{//费率
|
{//费率
|
||||||
path: 'rate',
|
path: 'rate',
|
||||||
name: 'Rate',
|
name: 'Rate',
|
||||||
component: () => import('../views/rate/index.vue'),
|
component: () => import('../views/rate/index.vue'),
|
||||||
meta: {
|
meta: {title: '费率页面',
|
||||||
title: '费率页面',
|
|
||||||
description:i18n.t(`seo.rate`),
|
description:i18n.t(`seo.rate`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,费率页面,挖矿费率,收益计算,Mining Pool,Rate,Mining fee rate,Profit calculation'
|
// keywords: 'M2Pool 矿池,费率页面,挖矿费率,收益计算,Mining Pool,Rate,Mining fee rate,Profit calculation'
|
||||||
@@ -232,8 +93,7 @@ const childrenRoutes = [
|
|||||||
path: 'allocationExplanation',
|
path: 'allocationExplanation',
|
||||||
name: 'AllocationExplanation',
|
name: 'AllocationExplanation',
|
||||||
component: () => import('../views/allocationExplanation/index.vue'),
|
component: () => import('../views/allocationExplanation/index.vue'),
|
||||||
meta: {
|
meta: {title: '分配说明页面',
|
||||||
title: '分配说明页面',
|
|
||||||
description:i18n.t(`seo.rate`),
|
description:i18n.t(`seo.rate`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: '分配、转账说明,矿池分配,转账说明,Allocation,Transfer,Mining Pool,Pool allocation,Transfer instructions'
|
// keywords: '分配、转账说明,矿池分配,转账说明,Allocation,Transfer,Mining Pool,Pool allocation,Transfer instructions'
|
||||||
@@ -247,8 +107,7 @@ const childrenRoutes = [
|
|||||||
path: 'apiFile',
|
path: 'apiFile',
|
||||||
name: 'ApiFile',
|
name: 'ApiFile',
|
||||||
component: () => import('../views/apiFile/index.vue'),
|
component: () => import('../views/apiFile/index.vue'),
|
||||||
meta: {
|
meta: {title: 'API文档页面',
|
||||||
title: 'API文档页面',
|
|
||||||
description:i18n.t(`seo.apiFile`),
|
description:i18n.t(`seo.apiFile`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,API 文档,认证 token,接口调用,API file,authentication token,Interface call'
|
// keywords: 'M2Pool 矿池,API 文档,认证 token,接口调用,API file,authentication token,Interface call'
|
||||||
@@ -259,29 +118,11 @@ const childrenRoutes = [
|
|||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{//在线客服
|
|
||||||
path: 'customerService',
|
|
||||||
name: 'CustomerService',
|
|
||||||
component: () => import('../views/customerService/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '在线客服',
|
|
||||||
description: i18n.t(`seo.apiFile`),
|
|
||||||
allAuthority: [`customer_service`, `admin`,],//客服权限
|
|
||||||
// keywords: 'M2Pool 矿池,API 文档,认证 token,接口调用,API file,authentication token,Interface call'
|
|
||||||
keywords: {
|
|
||||||
en: 'API file,authentication token,Interface call',
|
|
||||||
zh: 'M2Pool 矿池,API 文档,认证 token,接口调用'
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{//接入矿池页面
|
{//接入矿池页面
|
||||||
path: '/:lang/AccessMiningPool',
|
path: '/:lang/AccessMiningPool',
|
||||||
name: 'AccessMiningPool',
|
name: 'AccessMiningPool',
|
||||||
component: () => import('../views/AccessMiningPool/index.vue'),
|
component: () => import('../views/AccessMiningPool/index.vue'),
|
||||||
meta: {
|
meta: {title: '接入矿池页面',
|
||||||
title: '接入矿池页面',
|
|
||||||
description:i18n.t(`seo.allocationExplanation`),
|
description:i18n.t(`seo.allocationExplanation`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,接入矿池,币种接入,挖矿指南,Access to Mining Pools,Coin Access,Mining Guide'
|
// keywords: 'M2Pool 矿池,接入矿池,币种接入,挖矿指南,Access to Mining Pools,Coin Access,Mining Guide'
|
||||||
@@ -296,8 +137,7 @@ const childrenRoutes = [
|
|||||||
path: 'nexaAccess',
|
path: 'nexaAccess',
|
||||||
name: 'NexaAccess',
|
name: 'NexaAccess',
|
||||||
component: () => import('../views/AccessMiningPool/nexaAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/nexaAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'nexa 挖矿页面',
|
||||||
title: 'nexa 挖矿页面',
|
|
||||||
description:i18n.t(`seo.nexaAccess`),
|
description:i18n.t(`seo.nexaAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
@@ -313,8 +153,7 @@ const childrenRoutes = [
|
|||||||
path: 'rxdAccess',
|
path: 'rxdAccess',
|
||||||
name: 'RxdAccess',
|
name: 'RxdAccess',
|
||||||
component: () => import('../views/AccessMiningPool/rxdAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/rxdAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'rxd 挖矿页面',
|
||||||
title: 'rxd 挖矿页面',
|
|
||||||
description:i18n.t(`seo.rxdAccess`),
|
description:i18n.t(`seo.rxdAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'rxd,挖矿教程,Radiant接入,rxd Access,Radiant Access,Mining Tutorial,radiant'
|
// keywords: 'rxd,挖矿教程,Radiant接入,rxd Access,Radiant Access,Mining Tutorial,radiant'
|
||||||
@@ -328,8 +167,7 @@ const childrenRoutes = [
|
|||||||
path: 'monaAccess',
|
path: 'monaAccess',
|
||||||
name: 'MonaAccess',
|
name: 'MonaAccess',
|
||||||
component: () => import('../views/AccessMiningPool/monaAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/monaAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'mona 挖矿页面',
|
||||||
title: 'mona 挖矿页面',
|
|
||||||
description:i18n.t(`seo.monaAccess`),
|
description:i18n.t(`seo.monaAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'mona,挖矿教程,mona接入,Mona Access,MONA Access,Mining Tutorial'
|
// keywords: 'mona,挖矿教程,mona接入,Mona Access,MONA Access,Mining Tutorial'
|
||||||
@@ -344,8 +182,7 @@ const childrenRoutes = [
|
|||||||
path: 'grsAccess',
|
path: 'grsAccess',
|
||||||
name: 'GrsAccess',
|
name: 'GrsAccess',
|
||||||
component: () => import('../views/AccessMiningPool/grsAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/grsAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'grs 挖矿页面',
|
||||||
title: 'grs 挖矿页面',
|
|
||||||
description:i18n.t(`seo.grsAccess`),
|
description:i18n.t(`seo.grsAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'GRS,Grs接入,GRS Access,grs Access,Mining Tutorial'
|
// keywords: 'GRS,Grs接入,GRS Access,grs Access,Mining Tutorial'
|
||||||
@@ -360,8 +197,7 @@ const childrenRoutes = [
|
|||||||
path: 'dgbqAccess',
|
path: 'dgbqAccess',
|
||||||
name: 'DgbqAccess',
|
name: 'DgbqAccess',
|
||||||
component: () => import('../views/AccessMiningPool/dgbqAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/dgbqAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'Dgbq 挖矿页面',
|
||||||
title: 'Dgbq 挖矿页面',
|
|
||||||
description:i18n.t(`seo.dgbAccess`),
|
description:i18n.t(`seo.dgbAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'Dgbq,dgb(qubit)接入,Dgb(qubit) Access,DGB(qubit) Access,Mining Tutorial,DGB'
|
// keywords: 'Dgbq,dgb(qubit)接入,Dgb(qubit) Access,DGB(qubit) Access,Mining Tutorial,DGB'
|
||||||
@@ -376,8 +212,7 @@ const childrenRoutes = [
|
|||||||
path: 'dgboAccess',
|
path: 'dgboAccess',
|
||||||
name: 'DgboAccess',
|
name: 'DgboAccess',
|
||||||
component: () => import('../views/AccessMiningPool/dgboAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/dgboAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'Dgbo 挖矿页面',
|
||||||
title: 'Dgbo 挖矿页面',
|
|
||||||
description:i18n.t(`seo.dgbAccess`),
|
description:i18n.t(`seo.dgbAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'dgbo,dgb(odocrypt)接入,Dgb(odocrypt) Access,DGB(odocrypt) Access,Mining Tutorial,DGB'
|
// keywords: 'dgbo,dgb(odocrypt)接入,Dgb(odocrypt) Access,DGB(odocrypt) Access,Mining Tutorial,DGB'
|
||||||
@@ -392,8 +227,7 @@ const childrenRoutes = [
|
|||||||
path: 'dgbsAccess',
|
path: 'dgbsAccess',
|
||||||
name: 'DgbsAccess',
|
name: 'DgbsAccess',
|
||||||
component: () => import('../views/AccessMiningPool/dgbsAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/dgbsAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: 'Dgbs 挖矿页面',
|
||||||
title: 'Dgbs 挖矿页面',
|
|
||||||
description:i18n.t(`seo.dgbAccess`),
|
description:i18n.t(`seo.dgbAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'dgbs,dgb(skein)接入,Dgb(skein) Access,DGB(skein) Access,Mining Tutorial,DGB'
|
// keywords: 'dgbs,dgb(skein)接入,Dgb(skein) Access,DGB(skein) Access,Mining Tutorial,DGB'
|
||||||
@@ -408,8 +242,7 @@ const childrenRoutes = [
|
|||||||
path: 'enxAccess',
|
path: 'enxAccess',
|
||||||
name: 'EnxAccess',
|
name: 'EnxAccess',
|
||||||
component: () => import('../views/AccessMiningPool/enxAccess/index.vue'),
|
component: () => import('../views/AccessMiningPool/enxAccess/index.vue'),
|
||||||
meta: {
|
meta: {title: ' Entropyx(enx) 挖矿页面',
|
||||||
title: ' Entropyx(enx) 挖矿页面',
|
|
||||||
description:i18n.t(`seo.enxAccess`),
|
description:i18n.t(`seo.enxAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'Entropyx(Enx), Entropyx(enx)接入,enx,ENX,Mining Tutorial'
|
// keywords: 'Entropyx(Enx), Entropyx(enx)接入,enx,ENX,Mining Tutorial'
|
||||||
@@ -424,8 +257,7 @@ const childrenRoutes = [
|
|||||||
path: 'alphminingPool',
|
path: 'alphminingPool',
|
||||||
name: 'AlphminingPool',
|
name: 'AlphminingPool',
|
||||||
component: () => import('../views/AccessMiningPool/alphminingPool/index.vue'),
|
component: () => import('../views/AccessMiningPool/alphminingPool/index.vue'),
|
||||||
meta: {
|
meta: {title: ' alephium 挖矿页面',
|
||||||
title: ' alephium 挖矿页面',
|
|
||||||
description:i18n.t(`seo.alphAccess`),
|
description:i18n.t(`seo.alphAccess`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'Entropyx(Enx), Entropyx(enx)接入,enx,ENX,Mining Tutorial'
|
// keywords: 'Entropyx(Enx), Entropyx(enx)接入,enx,ENX,Mining Tutorial'
|
||||||
@@ -444,8 +276,7 @@ const childrenRoutes = [
|
|||||||
path: 'ServiceTerms',
|
path: 'ServiceTerms',
|
||||||
name: 'ServiceTerms',
|
name: 'ServiceTerms',
|
||||||
component: () => import('../views/ServiceTerms/index.vue'),
|
component: () => import('../views/ServiceTerms/index.vue'),
|
||||||
meta: {
|
meta: {title: '服务条款页面',
|
||||||
title: '服务条款页面',
|
|
||||||
description:i18n.t(`seo.ServiceTerms`),
|
description:i18n.t(`seo.ServiceTerms`),
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,服务条款,用户权益,权利义务,Terms of Service, User Rights, Rights and Obligations'
|
// keywords: 'M2Pool 矿池,服务条款,用户权益,权利义务,Terms of Service, User Rights, Rights and Obligations'
|
||||||
@@ -459,10 +290,9 @@ const childrenRoutes = [
|
|||||||
path: 'submitWorkOrder',
|
path: 'submitWorkOrder',
|
||||||
name: 'SubmitWorkOrder',
|
name: 'SubmitWorkOrder',
|
||||||
component: () => import('../views/submitWorkOrder/index.vue'),
|
component: () => import('../views/submitWorkOrder/index.vue'),
|
||||||
meta: {
|
meta: {title: '提交工单页面',
|
||||||
title: '提交工单页面',
|
|
||||||
description:i18n.t(`seo.submitWorkOrder`),
|
description:i18n.t(`seo.submitWorkOrder`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,提交工单,技术支持,问题处理,Mining Pool,Work Order Submission, Technical Support, Troubleshooting'
|
// keywords: 'M2Pool 矿池,提交工单,技术支持,问题处理,Mining Pool,Work Order Submission, Technical Support, Troubleshooting'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Mining Pool,Work Order Submission, Technical Support, Troubleshooting',
|
en: 'Mining Pool,Work Order Submission, Technical Support, Troubleshooting',
|
||||||
@@ -474,10 +304,9 @@ const childrenRoutes = [
|
|||||||
path: 'workOrderRecords',
|
path: 'workOrderRecords',
|
||||||
name: 'WorkOrderRecords',
|
name: 'WorkOrderRecords',
|
||||||
component: () => import('../views/workOrderRecords/index.vue'),
|
component: () => import('../views/workOrderRecords/index.vue'),
|
||||||
meta: {
|
meta: {title: '工单记录页面(用户)',
|
||||||
title: '工单记录页面(用户)',
|
|
||||||
description:i18n.t(`seo.workOrderRecords`),
|
description:i18n.t(`seo.workOrderRecords`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,用户工单记录,处理状态,问题进度,User Work Order Records, Processing Status, Issue Progress'
|
// keywords: 'M2Pool 矿池,用户工单记录,处理状态,问题进度,User Work Order Records, Processing Status, Issue Progress'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'User Work Order Records, Processing Status, Issue Progress',
|
en: 'User Work Order Records, Processing Status, Issue Progress',
|
||||||
@@ -489,10 +318,9 @@ const childrenRoutes = [
|
|||||||
path: 'userWorkDetails',
|
path: 'userWorkDetails',
|
||||||
name: 'UserWorkDetails',
|
name: 'UserWorkDetails',
|
||||||
component: () => import('../views/userWorkDetails/index.vue'),
|
component: () => import('../views/userWorkDetails/index.vue'),
|
||||||
meta: {
|
meta: {title: '工单详情页面(用户)',
|
||||||
title: '工单详情页面(用户)',
|
|
||||||
description:i18n.t(`seo.userWorkDetails`),
|
description:i18n.t(`seo.userWorkDetails`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,用户工单详情,问题描述,补充提交,User Work Order Details, Problem Description, Additional Submissions'
|
// keywords: 'M2Pool 矿池,用户工单详情,问题描述,补充提交,User Work Order Details, Problem Description, Additional Submissions'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'User Work Order Details, Problem Description, Additional Submissions',
|
en: 'User Work Order Details, Problem Description, Additional Submissions',
|
||||||
@@ -504,10 +332,9 @@ const childrenRoutes = [
|
|||||||
path: 'workOrderBackend',
|
path: 'workOrderBackend',
|
||||||
name: 'WorkOrderBackend',
|
name: 'WorkOrderBackend',
|
||||||
component: () => import('../views/workOrderBackend/index.vue'),
|
component: () => import('../views/workOrderBackend/index.vue'),
|
||||||
meta: {
|
meta: {title: '工单管理页面(后台)',
|
||||||
title: '工单管理页面(后台)',
|
|
||||||
description:"M2Pool 矿池后台工单管理页面,供 M2Pool 管理员查看和管理用户提交的工单记录,确保问题及时处理,提升用户体验。",
|
description:"M2Pool 矿池后台工单管理页面,供 M2Pool 管理员查看和管理用户提交的工单记录,确保问题及时处理,提升用户体验。",
|
||||||
allAuthority: [`back_admin`],
|
allAuthority:[`admin`],
|
||||||
// keywords: 'M2Pool 矿池,后台工单管理,用户工单,及时处理,Back-office work order management, user work orders, timely processing'
|
// keywords: 'M2Pool 矿池,后台工单管理,用户工单,及时处理,Back-office work order management, user work orders, timely processing'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Back-office work order management, user work orders, timely processing',
|
en: 'Back-office work order management, user work orders, timely processing',
|
||||||
@@ -519,10 +346,9 @@ const childrenRoutes = [
|
|||||||
path: 'BKWorkDetails',
|
path: 'BKWorkDetails',
|
||||||
name: 'BKWorkDetails',
|
name: 'BKWorkDetails',
|
||||||
component: () => import('../views/BKWorkDetails/index.vue'),
|
component: () => import('../views/BKWorkDetails/index.vue'),
|
||||||
meta: {
|
meta: {title: '工单详情页面(后台)',
|
||||||
title: '工单详情页面(后台)',
|
|
||||||
description:"M2Pool 矿池后台工单详情页面,管理员可在此查看提交工单的详细情况,包括提交时间、详细问题描述以及处理过程,并通过本页面对该工单进行回复处理。",
|
description:"M2Pool 矿池后台工单详情页面,管理员可在此查看提交工单的详细情况,包括提交时间、详细问题描述以及处理过程,并通过本页面对该工单进行回复处理。",
|
||||||
allAuthority: [`back_admin`],
|
allAuthority:[`admin`],
|
||||||
// keywords: 'M2Pool 矿池,后台工单详情,问题处理,回复工单,Backend Work Order Details, Problem Handling, Responding to Work Orders'
|
// keywords: 'M2Pool 矿池,后台工单详情,问题处理,回复工单,Backend Work Order Details, Problem Handling, Responding to Work Orders'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Backend Work Order Details, Problem Handling, Responding to Work Orders',
|
en: 'Backend Work Order Details, Problem Handling, Responding to Work Orders',
|
||||||
@@ -534,8 +360,7 @@ const childrenRoutes = [
|
|||||||
path: 'dataDisplay',
|
path: 'dataDisplay',
|
||||||
name: 'DataDisplay',
|
name: 'DataDisplay',
|
||||||
component: () => import('../views/dataDisplay/index.vue'),
|
component: () => import('../views/dataDisplay/index.vue'),
|
||||||
meta: {
|
meta: {title: '数据展示页面',
|
||||||
title: '数据展示页面',
|
|
||||||
description:"M2Pool 矿池数据展示页面",
|
description:"M2Pool 矿池数据展示页面",
|
||||||
allAuthority:[`all`],
|
allAuthority:[`all`],
|
||||||
// keywords: 'M2Pool 矿池,数据展示,Mining Pool,Data Display'
|
// keywords: 'M2Pool 矿池,数据展示,Mining Pool,Data Display'
|
||||||
@@ -545,71 +370,13 @@ const childrenRoutes = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{//公告中心
|
|
||||||
path: 'announcements',
|
|
||||||
name: 'Announcements',
|
|
||||||
component: () => import('../views/announcements/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '公告中心',
|
|
||||||
description: i18n.t(`seo.announcements`) || 'M2Pool 矿池公告中心,提供最新的公告、通知和重要信息,让用户及时了解矿池的最新动态和服务变更。',
|
|
||||||
allAuthority: [`all`],
|
|
||||||
keywords: {
|
|
||||||
en: 'Announcement Center,Latest Announcements,Mining Pool News,Service Updates,Important Notices',
|
|
||||||
zh: 'M2Pool 矿池,公告中心,最新公告,矿池动态,服务更新,重要通知'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//公告详情
|
|
||||||
path: 'announcementDetails',
|
|
||||||
name: 'AnnouncementDetails',
|
|
||||||
component: () => import('../views/announcementDetails/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '公告详情',
|
|
||||||
// description: i18n.t(`seo.announcements`) || 'M2Pool 矿池公告中心,提供最新的公告、通知和重要信息,让用户及时了解矿池的最新动态和服务变更。',
|
|
||||||
allAuthority: [`all`],
|
|
||||||
// keywords: {
|
|
||||||
// en: 'Announcement Center,Latest Announcements,Mining Pool News,Service Updates,Important Notices',
|
|
||||||
// zh: 'M2Pool 矿池,公告中心,最新公告,矿池动态,服务更新,重要通知'
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//常见问题
|
|
||||||
path: 'commonProblem',
|
|
||||||
name: 'CommonProblem',
|
|
||||||
component: () => import('../views/commonProblem/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '常见问题',
|
|
||||||
// description: i18n.t(`seo.announcements`) || 'M2Pool 矿池公告中心,提供最新的公告、通知和重要信息,让用户及时了解矿池的最新动态和服务变更。',
|
|
||||||
allAuthority: [`all`],
|
|
||||||
// keywords: {
|
|
||||||
// en: 'Announcement Center,Latest Announcements,Mining Pool News,Service Updates,Important Notices',
|
|
||||||
// zh: 'M2Pool 矿池,公告中心,最新公告,矿池动态,服务更新,重要通知'
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{//搜索结果页面
|
|
||||||
path: 'searchResult',
|
|
||||||
name: 'SearchResult',
|
|
||||||
component: () => import('../views/searchResult/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '搜索结果',
|
|
||||||
// description: i18n.t(`seo.announcements`) || 'M2Pool 矿池公告中心,提供最新的公告、通知和重要信息,让用户及时了解矿池的最新动态和服务变更。',
|
|
||||||
allAuthority: [`all`],
|
|
||||||
// keywords: {
|
|
||||||
// en: 'Announcement Center,Latest Announcements,Mining Pool News,Service Updates,Important Notices',
|
|
||||||
// zh: 'M2Pool 矿池,公告中心,最新公告,矿池动态,服务更新,重要通知'
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
{//警报通知
|
{//警报通知
|
||||||
path: 'alerts',
|
path: 'alerts',
|
||||||
name: 'Alerts',
|
name: 'Alerts',
|
||||||
component: () => import('../views/alerts/index.vue'),
|
component: () => import('../views/alerts/index.vue'),
|
||||||
meta: {
|
meta: {title: '警报通知',
|
||||||
title: '警报通知',
|
|
||||||
description:i18n.t(`seo.alerts`),
|
description:i18n.t(`seo.alerts`),
|
||||||
allAuthority: [`admin`, `registered`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool, 矿池,离线告警设置,矿机离线,Mining Pool,Offline Alarm Setting,Mining Machine Offline'
|
// keywords: 'M2Pool, 矿池,离线告警设置,矿机离线,Mining Pool,Offline Alarm Setting,Mining Machine Offline'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Mining Pool,Offline Alarm Setting,Mining Machine Offline',
|
en: 'Mining Pool,Offline Alarm Setting,Mining Machine Offline',
|
||||||
@@ -623,10 +390,9 @@ const childrenRoutes = [
|
|||||||
name: 'PersonalCenter',
|
name: 'PersonalCenter',
|
||||||
// redirect: "/personalCenter/personalMining",
|
// redirect: "/personalCenter/personalMining",
|
||||||
component: () => import('../views/personalCenter/index.vue'),
|
component: () => import('../views/personalCenter/index.vue'),
|
||||||
meta: {
|
meta: {title: '个人中心页面',
|
||||||
title: '个人中心页面',
|
|
||||||
description:i18n.t(`seo.personalCenter`),
|
description:i18n.t(`seo.personalCenter`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人中心,挖矿账户,只读页面设置,安全设置,API密钥生成,Personal Center,Mining Account,Read-Only Page Setup,Security Settings,API Key Generation'
|
// keywords: 'M2Pool 矿池,个人中心,挖矿账户,只读页面设置,安全设置,API密钥生成,Personal Center,Mining Account,Read-Only Page Setup,Security Settings,API Key Generation'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Personal Center,Mining Account,Read-Only Page Setup,Security Settings,API Key Generation',
|
en: 'Personal Center,Mining Account,Read-Only Page Setup,Security Settings,API Key Generation',
|
||||||
@@ -638,10 +404,9 @@ const childrenRoutes = [
|
|||||||
path: 'personalMining',
|
path: 'personalMining',
|
||||||
name: 'PersonalMining',
|
name: 'PersonalMining',
|
||||||
component: () => import('../views/personalCenter/personalMining/index.vue'),
|
component: () => import('../views/personalCenter/personalMining/index.vue'),
|
||||||
meta: {
|
meta: {title: '挖矿账户设置页面',
|
||||||
title: '挖矿账户设置页面',
|
|
||||||
description:i18n.t(`seo.personalMining`),
|
description:i18n.t(`seo.personalMining`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人中心,挖矿账户设置,币种账户,Personal Center,Mining Account Settings,Coin Accounts'
|
// keywords: 'M2Pool 矿池,个人中心,挖矿账户设置,币种账户,Personal Center,Mining Account Settings,Coin Accounts'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Personal Center,Mining Account Settings,Coin Accounts',
|
en: 'Personal Center,Mining Account Settings,Coin Accounts',
|
||||||
@@ -653,10 +418,9 @@ const childrenRoutes = [
|
|||||||
path: 'readOnly',
|
path: 'readOnly',
|
||||||
name: 'ReadOnly',
|
name: 'ReadOnly',
|
||||||
component: () => import('../views/personalCenter/readOnly/index.vue'),
|
component: () => import('../views/personalCenter/readOnly/index.vue'),
|
||||||
meta: {
|
meta: {title: '只读页面设置',
|
||||||
title: '只读页面设置',
|
|
||||||
description:i18n.t(`seo.readOnly`),
|
description:i18n.t(`seo.readOnly`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人中心,只读页面设置,矿池分享,Personal Center,Read-Only Page Setting,Mining Pool Sharing'
|
// keywords: 'M2Pool 矿池,个人中心,只读页面设置,矿池分享,Personal Center,Read-Only Page Setting,Mining Pool Sharing'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Personal Center,Read-Only Page Setting,Mining Pool Sharing',
|
en: 'Personal Center,Read-Only Page Setting,Mining Pool Sharing',
|
||||||
@@ -668,10 +432,9 @@ const childrenRoutes = [
|
|||||||
path: 'securitySetting',
|
path: 'securitySetting',
|
||||||
name: 'SecuritySetting',
|
name: 'SecuritySetting',
|
||||||
component: () => import('../views/personalCenter/securitySetting/index.vue'),
|
component: () => import('../views/personalCenter/securitySetting/index.vue'),
|
||||||
meta: {
|
meta: {title: '安全设置页面',
|
||||||
title: '安全设置页面',
|
|
||||||
description:i18n.t(`seo.securitySetting`),
|
description:i18n.t(`seo.securitySetting`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,安全设置,密码修改,Security settings, password change'
|
// keywords: 'M2Pool 矿池,安全设置,密码修改,Security settings, password change'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Security settings, password change',
|
en: 'Security settings, password change',
|
||||||
@@ -683,10 +446,9 @@ const childrenRoutes = [
|
|||||||
path: 'personal',
|
path: 'personal',
|
||||||
name: 'personal',
|
name: 'personal',
|
||||||
component: () => import('../views/personalCenter/personal/index.vue'),
|
component: () => import('../views/personalCenter/personal/index.vue'),
|
||||||
meta: {
|
meta: {title: '个人信息页面',
|
||||||
title: '个人信息页面',
|
|
||||||
description:i18n.t(`seo.personal`),
|
description:i18n.t(`seo.personal`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人信息,登录历史,Personal Information, Login History'
|
// keywords: 'M2Pool 矿池,个人信息,登录历史,Personal Information, Login History'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Personal Information, Login History',
|
en: 'Personal Information, Login History',
|
||||||
@@ -698,10 +460,9 @@ const childrenRoutes = [
|
|||||||
path: 'miningReport',
|
path: 'miningReport',
|
||||||
name: 'MiningReport',
|
name: 'MiningReport',
|
||||||
component: () => import('../views/personalCenter/miningReport/index.vue'),
|
component: () => import('../views/personalCenter/miningReport/index.vue'),
|
||||||
meta: {
|
meta: {title: '挖矿报告页面',
|
||||||
title: '挖矿报告页面',
|
|
||||||
description:i18n.t(`seo.miningReport`),
|
description:i18n.t(`seo.miningReport`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人中心,挖矿报告,订阅服务,Mining Report, Subscription Service'
|
// keywords: 'M2Pool 矿池,个人中心,挖矿报告,订阅服务,Mining Report, Subscription Service'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'Mining Report, Subscription Service',
|
en: 'Mining Report, Subscription Service',
|
||||||
@@ -714,10 +475,9 @@ const childrenRoutes = [
|
|||||||
path: 'personalAPI',
|
path: 'personalAPI',
|
||||||
name: 'PersonalAPI',
|
name: 'PersonalAPI',
|
||||||
component: () => import('../views/personalCenter/personalAPI/index.vue'),
|
component: () => import('../views/personalCenter/personalAPI/index.vue'),
|
||||||
meta: {
|
meta: {title: 'API页面',
|
||||||
title: 'API页面',
|
|
||||||
description:i18n.t(`seo.personalAPI`),
|
description:i18n.t(`seo.personalAPI`),
|
||||||
allAuthority: [`admin`, `registered`, `customer_service`, `back_admin`],
|
allAuthority:[`admin`,`registered`],
|
||||||
// keywords: 'M2Pool 矿池,个人中心,API 页面,API密钥生成,API Page,API Key Generation'
|
// keywords: 'M2Pool 矿池,个人中心,API 页面,API密钥生成,API Page,API Key Generation'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'API Page,API Key Generation',
|
en: 'API Page,API Key Generation',
|
||||||
@@ -753,8 +513,7 @@ const staticRoutes = [
|
|||||||
path: '/:lang/register',
|
path: '/:lang/register',
|
||||||
name: 'Register',
|
name: 'Register',
|
||||||
component: () => import('../views/register/register.vue'),
|
component: () => import('../views/register/register.vue'),
|
||||||
meta: {
|
meta: {title: '注册页面',description:"M2Pool 矿池注册页面,新用户可在此便捷注册账号,加入 M2Pool 矿池大家庭。",allAuthority:[`all`],
|
||||||
title: '注册页面', description: "M2Pool 矿池注册页面,新用户可在此便捷注册账号,加入 M2Pool 矿池大家庭。", allAuthority: [`all`],
|
|
||||||
// keywords: 'M2Pool 矿池,注册页面,新用户注册,账号创建'
|
// keywords: 'M2Pool 矿池,注册页面,新用户注册,账号创建'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'M2Pool Mining Pool,register page,new user registration,account creation',
|
en: 'M2Pool Mining Pool,register page,new user registration,account creation',
|
||||||
@@ -766,8 +525,7 @@ const staticRoutes = [
|
|||||||
path: '/:lang/simulation',
|
path: '/:lang/simulation',
|
||||||
name: 'simulation',
|
name: 'simulation',
|
||||||
component: () => import('../views/simulation.vue'),
|
component: () => import('../views/simulation.vue'),
|
||||||
meta: {
|
meta: {title: '测试页面',description:"M2Pool 矿池测试页面,用于进行系统功能的模拟和测试,确保矿池稳定运行",allAuthority:[`all`],
|
||||||
title: '测试页面', description: "M2Pool 矿池测试页面,用于进行系统功能的模拟和测试,确保矿池稳定运行", allAuthority: [`all`],
|
|
||||||
// keywords: 'M2Pool 矿池,测试页面,系统测试,稳定运行'
|
// keywords: 'M2Pool 矿池,测试页面,系统测试,稳定运行'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'M2Pool Mining Pool,test page,system test,stable operation',
|
en: 'M2Pool Mining Pool,test page,system test,stable operation',
|
||||||
@@ -775,20 +533,6 @@ const staticRoutes = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/:lang/splitEditorDemo',
|
|
||||||
name: 'splitEditorDemo',
|
|
||||||
component: () => import('../views/splitEditorDemo/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '分屏编辑器演示',
|
|
||||||
description: "M2Pool 分屏编辑器演示页面,支持编辑、预览、分屏三种模式的富文本编辑器",
|
|
||||||
allAuthority: [`all`],
|
|
||||||
keywords: {
|
|
||||||
en: 'split screen editor,rich text editor,real-time preview,WYSIWYG editor',
|
|
||||||
zh: '分屏编辑器,富文本编辑器,实时预览,所见即所得编辑器'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -796,8 +540,7 @@ const staticRoutes = [
|
|||||||
path: '/:lang/resetPassword',
|
path: '/:lang/resetPassword',
|
||||||
name: 'ResetPassword',
|
name: 'ResetPassword',
|
||||||
component: () => import('../views/resetPassword/index.vue'),
|
component: () => import('../views/resetPassword/index.vue'),
|
||||||
meta: {
|
meta: {title: '重置密码页面',description:"M2Pool 矿池重置密码页面,用户可在此修改矿池网站账号密码,保障账户安全。",allAuthority:[`all`],
|
||||||
title: '重置密码页面', description: "M2Pool 矿池重置密码页面,用户可在此修改矿池网站账号密码,保障账户安全。", allAuthority: [`all`],
|
|
||||||
// keywords: 'M2Pool 矿池,重置密码,修改密码,账户安全'
|
// keywords: 'M2Pool 矿池,重置密码,修改密码,账户安全'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'M2Pool Mining Pool,reset password,modify password,account security',
|
en: 'M2Pool Mining Pool,reset password,modify password,account security',
|
||||||
@@ -808,8 +551,7 @@ const staticRoutes = [
|
|||||||
{//404
|
{//404
|
||||||
path: '/:lang/404',
|
path: '/:lang/404',
|
||||||
component: () => import('../views/page404.vue'),
|
component: () => import('../views/page404.vue'),
|
||||||
meta: {
|
meta: {title: '404页面',description:"M2Pool 矿池 404 页面,当 URL 错误时将跳转至此页面,提示用户页面不存在。",allAuthority:[`all`],
|
||||||
title: '404页面', description: "M2Pool 矿池 404 页面,当 URL 错误时将跳转至此页面,提示用户页面不存在。", allAuthority: [`all`],
|
|
||||||
// keywords: 'M2Pool 矿池,404 页面,页面不存在,错误跳转'
|
// keywords: 'M2Pool 矿池,404 页面,页面不存在,错误跳转'
|
||||||
keywords:{
|
keywords:{
|
||||||
en: 'M2Pool Mining Pool,404 page,page not found,error redirect',
|
en: 'M2Pool Mining Pool,404 page,page not found,error redirect',
|
||||||
@@ -870,129 +612,90 @@ const router = new VueRouter({
|
|||||||
base: process.env.BASE_URL,
|
base: process.env.BASE_URL,
|
||||||
routes,
|
routes,
|
||||||
strict: true, // 启用严格模式,不允许尾部斜杠
|
strict: true, // 启用严格模式,不允许尾部斜杠
|
||||||
scrollBehavior(to, from, savedPosition) { //每次路由跳转时,滚动到顶部
|
|
||||||
// 如果有保存的滚动位置(比如浏览器前进后退),就用它
|
|
||||||
if (savedPosition) {
|
|
||||||
return savedPosition;
|
|
||||||
} else {
|
|
||||||
// 否则滚动到顶部,并使用平滑滚动
|
|
||||||
return { x: 0, y: 0, behavior: 'smooth' };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
router.afterEach(() => {
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
// 滚动主内容区
|
|
||||||
const contentMain = document.querySelector('.el-main');
|
|
||||||
if (contentMain) {
|
|
||||||
contentMain.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
|
||||||
}
|
|
||||||
// 兼容其它页面(如登录页等)
|
|
||||||
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
const lang = to.params.lang || (localStorage.getItem('lang') || 'en');
|
// 检查语言参数
|
||||||
let token = null;
|
const lang = to.params.lang;
|
||||||
try {
|
const supportedLanguages = ['zh', 'en'];
|
||||||
token = JSON.parse(localStorage.getItem('token'));
|
|
||||||
} catch (e) {
|
// 如果路径以斜杠结尾且不是根路径,则重定向
|
||||||
token = null;
|
if (to.path.endsWith('/') && to.path.length > 1) {
|
||||||
|
const path = to.path.slice(0, -1);
|
||||||
|
return next({
|
||||||
|
path,
|
||||||
|
query: to.query,
|
||||||
|
hash: to.hash,
|
||||||
|
params: to.params
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// 权限判断
|
|
||||||
let jurisdiction = null;
|
if (!lang && to.path !== '/') {
|
||||||
|
const defaultLang = localStorage.getItem('lang') || 'en';
|
||||||
|
return next(`/${defaultLang}${to.path}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = localStorage.getItem("jurisdiction");
|
||||||
|
let jurisdiction =JSON.parse(data);
|
||||||
|
|
||||||
|
localStorage.setItem('superReportError',"")
|
||||||
|
let element = document.getElementsByClassName('el-main')[0];
|
||||||
|
if(element){
|
||||||
|
element.scrollTop = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let token
|
||||||
try{
|
try{
|
||||||
jurisdiction = JSON.parse(localStorage.getItem("jurisdiction"));
|
token =JSON.parse(localStorage.getItem('token'))
|
||||||
}catch(e){
|
}catch(e){
|
||||||
jurisdiction = null;
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
|
||||||
|
|
||||||
// --------------------------
|
if (to.path === `/${lang}/login`|| to.path === `/${lang}/register`) {
|
||||||
// 未登录
|
next({ path: `/${lang}` })
|
||||||
if (!token) {
|
}else if(to.meta.allAuthority && to.meta.allAuthority[0] ==`all`){
|
||||||
console.log(`未登录`);
|
next()
|
||||||
if (
|
}else if(jurisdiction.roleKey && to.meta.allAuthority&&to.meta.allAuthority.some(item=>item == jurisdiction.roleKey )){
|
||||||
to.meta.allAuthority &&
|
next()
|
||||||
(
|
|
||||||
to.meta.allAuthority[0] === 'all' ||
|
|
||||||
(jurisdiction && jurisdiction.roleKey && to.meta.allAuthority.includes(jurisdiction.roleKey))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return next();
|
|
||||||
}else{
|
}else{
|
||||||
|
console.log(to.meta.allAuthority,to.path,"权限");
|
||||||
|
|
||||||
|
Message({//权限不足
|
||||||
// 无权限
|
|
||||||
Message({
|
|
||||||
showClose: true,
|
showClose: true,
|
||||||
message:i18n.t(`mining.jurisdiction`),
|
message:i18n.t(`mining.jurisdiction`),
|
||||||
type: 'error'
|
type: 'error'
|
||||||
});
|
});
|
||||||
return next({ path: `/${lang}/login` });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
|
||||||
if (jurisdiction && jurisdiction.roleKey == `back_admin`) {
|
let paths = [`/${lang}/miningAccount`,`/${lang}/workOrderRecords`,`/${lang}/userWorkDetails`,`/${lang}/submitWorkOrder`,`/${lang}/workOrderBackend`,`/${lang}/BKWorkDetails`]
|
||||||
if (to.name == 'Login' || to.name == 'Register' || jurisdiction && jurisdiction.roleKey && to.meta.allAuthority.includes(jurisdiction.roleKey)) {
|
if (paths.includes(to.path) || to.path.includes(`personalCenter`) ) {
|
||||||
return next();
|
|
||||||
} else if(to.path == `/${lang}`) {
|
Message({//权限不足
|
||||||
return next({ path: `/${lang}/userManagement` });
|
|
||||||
}else {
|
|
||||||
// 无权限
|
|
||||||
Message({
|
|
||||||
showClose: true,
|
showClose: true,
|
||||||
message: `当前身份只能访问后台管理系统`,
|
message:i18n.t(`mining.logInFirst`),
|
||||||
type: 'error'
|
type: 'error'
|
||||||
});
|
});
|
||||||
localStorage.setItem("activeIndex", `1`);
|
|
||||||
return next({ path: `/${lang}/broadcast` });
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
next({ path: `/${lang}/login` })
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (to.name === 'Login' || to.name === 'Register') {
|
next()
|
||||||
return next({ path: `/${lang}` });
|
|
||||||
} else if (to.meta.allAuthority &&
|
|
||||||
(
|
|
||||||
to.meta.allAuthority[0] === 'all' ||
|
|
||||||
(jurisdiction && jurisdiction.roleKey && to.meta.allAuthority.includes(jurisdiction.roleKey))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return next();
|
|
||||||
} else {
|
|
||||||
// 无权限
|
|
||||||
Message({
|
|
||||||
showClose: true,
|
|
||||||
message: i18n.t(`mining.jurisdiction`),
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
return next({ path: `/${lang}/login` });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,48 +5,12 @@ Vue.use(Vuex)
|
|||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
isLoggedIn: false,
|
|
||||||
userInfo: null
|
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
isLoggedIn: state => state.isLoggedIn,
|
|
||||||
userInfo: state => state.userInfo
|
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
SET_LOGIN_STATE(state, isLoggedIn) {
|
|
||||||
state.isLoggedIn = isLoggedIn
|
|
||||||
},
|
|
||||||
SET_USER_INFO(state, userInfo) {
|
|
||||||
state.userInfo = userInfo
|
|
||||||
},
|
|
||||||
CLEAR_USER_DATA(state) {
|
|
||||||
state.isLoggedIn = false
|
|
||||||
state.userInfo = null
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// 退出登录
|
|
||||||
async logout({ commit }) {
|
|
||||||
try {
|
|
||||||
// 清除本地存储
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
localStorage.removeItem('userEmail')
|
|
||||||
localStorage.removeItem('jurisdiction')
|
|
||||||
|
|
||||||
// 清除 Vuex 状态
|
|
||||||
commit('CLEAR_USER_DATA')
|
|
||||||
|
|
||||||
// 触发全局事件,通知其他组件用户已退出
|
|
||||||
if (Vue.prototype.$bus) {
|
|
||||||
Vue.prototype.$bus.$emit('user-logged-out')
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
} catch (error) {
|
|
||||||
console.error('退出登录失败:', error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
/**
|
|
||||||
* 错误提示管理器
|
|
||||||
* 用于控制错误提示的频率,避免短时间内重复显示相同类型的错误
|
|
||||||
*/
|
|
||||||
class ErrorNotificationManager {
|
|
||||||
constructor() {
|
|
||||||
// 记录最近显示的错误信息
|
|
||||||
this.recentErrors = new Map();
|
|
||||||
// 默认节流时间 (30秒)
|
|
||||||
this.throttleTime = 3000;
|
|
||||||
// 错误类型映射
|
|
||||||
this.errorTypes = {
|
|
||||||
'Network Error': 'network',
|
|
||||||
'timeout': 'timeout',
|
|
||||||
'Request failed with status code': 'statusCode',
|
|
||||||
// 添加网络状态类型
|
|
||||||
'networkReconnected': 'networkStatus',
|
|
||||||
'NetworkError': 'network'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取错误类型
|
|
||||||
* @param {String} message 错误信息
|
|
||||||
* @returns {String} 错误类型
|
|
||||||
*/
|
|
||||||
getErrorType(message) {
|
|
||||||
for (const [key, type] of Object.entries(this.errorTypes)) {
|
|
||||||
if (message.includes(key)) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查是否可以显示错误
|
|
||||||
* @param {String} message 错误信息
|
|
||||||
* @returns {Boolean} 是否可以显示
|
|
||||||
*/
|
|
||||||
canShowError(message) {
|
|
||||||
const errorType = this.getErrorType(message);
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
// 检查同类型的错误是否最近已经显示过
|
|
||||||
if (this.recentErrors.has(errorType)) {
|
|
||||||
const lastTime = this.recentErrors.get(errorType);
|
|
||||||
if (now - lastTime < this.throttleTime) {
|
|
||||||
console.log(`[错误提示] 已抑制重复错误: ${errorType}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新最后显示时间
|
|
||||||
this.recentErrors.set(errorType, now);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理过期的错误记录
|
|
||||||
*/
|
|
||||||
cleanup() {
|
|
||||||
const now = Date.now();
|
|
||||||
this.recentErrors.forEach((time, type) => {
|
|
||||||
if (now - time > this.throttleTime) {
|
|
||||||
this.recentErrors.delete(type);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建单例实例
|
|
||||||
const errorNotificationManager = new ErrorNotificationManager();
|
|
||||||
export default errorNotificationManager;
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动恢复加载状态的指令
|
|
||||||
* 用法: v-loading-recovery="{ loading: 'loadingProp', recovery: ['method1', 'method2'] }"
|
|
||||||
*/
|
|
||||||
export const loadingRecoveryDirective = {
|
|
||||||
// 当绑定元素插入到 DOM 中时
|
|
||||||
inserted(el, binding, vnode) {
|
|
||||||
const component = vnode.context;
|
|
||||||
const { loading, recovery } = binding.value || {};
|
|
||||||
|
|
||||||
if (!loading || !recovery || !Array.isArray(recovery)) return;
|
|
||||||
|
|
||||||
// 为组件添加加载状态恢复的逻辑
|
|
||||||
const handleNetworkRecovery = () => {
|
|
||||||
// 当网络恢复时,自动设置loading为false
|
|
||||||
if (component[loading]) {
|
|
||||||
component[loading] = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 保存到元素上,以便后续清理
|
|
||||||
el._loadingRecovery = handleNetworkRecovery;
|
|
||||||
window.addEventListener('network-retry-complete', handleNetworkRecovery);
|
|
||||||
|
|
||||||
console.log(`[LoadingRecovery] 添加加载状态恢复: ${loading}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 当指令与元素解绑时
|
|
||||||
unbind(el) {
|
|
||||||
// 清理事件监听
|
|
||||||
if (el._loadingRecovery) {
|
|
||||||
window.removeEventListener('network-retry-complete', el._loadingRecovery);
|
|
||||||
delete el._loadingRecovery;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 注册全局指令
|
|
||||||
Vue.directive('loading-recovery', loadingRecoveryDirective);
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
/**
|
|
||||||
* 密码强度逐项校验工具
|
|
||||||
* @description 提供分步密码校验,精确指出每一项不符合的要求
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码校验规则配置
|
|
||||||
*/
|
|
||||||
export const PASSWORD_RULES = {
|
|
||||||
minLength: 8,
|
|
||||||
maxLength: 32,
|
|
||||||
requireLowercase: true,
|
|
||||||
requireUppercase: true,
|
|
||||||
requireNumber: true,
|
|
||||||
requireSpecialChar: true,
|
|
||||||
allowChinese: false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 允许的特殊字符列表(用于显示给用户)
|
|
||||||
* 实际上所有非字母数字字符都可以,这里列出常用的
|
|
||||||
*/
|
|
||||||
export const ALLOWED_SPECIAL_CHARS = '!@#$%^&*()_+-=[]{}|;:\'",.<>?/\\`~'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验结果接口
|
|
||||||
* @typedef {Object} ValidationResult
|
|
||||||
* @property {boolean} valid - 是否通过校验
|
|
||||||
* @property {Array<string>} errors - 错误信息数组(i18n key)
|
|
||||||
* @property {Object} details - 每项规则的详细校验结果
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码逐项校验函数
|
|
||||||
* @param {string} password - 待校验的密码
|
|
||||||
* @returns {ValidationResult} 校验结果对象
|
|
||||||
*/
|
|
||||||
export function validatePassword(password) {
|
|
||||||
const result = {
|
|
||||||
valid: true,
|
|
||||||
errors: [],
|
|
||||||
details: {
|
|
||||||
length: false,
|
|
||||||
hasLowercase: false,
|
|
||||||
hasUppercase: false,
|
|
||||||
hasNumber: false,
|
|
||||||
hasSpecialChar: false,
|
|
||||||
noChinese: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 检查长度
|
|
||||||
if (password.length < PASSWORD_RULES.minLength) {
|
|
||||||
result.errors.push('passwordError.tooShort')
|
|
||||||
result.valid = false
|
|
||||||
} else if (password.length > PASSWORD_RULES.maxLength) {
|
|
||||||
result.errors.push('passwordError.tooLong')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.length = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查是否包含中文
|
|
||||||
const chineseRegex = /[\u4e00-\u9fa5]/
|
|
||||||
if (chineseRegex.test(password)) {
|
|
||||||
result.errors.push('passwordError.containsChinese')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.noChinese = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 检查小写字母
|
|
||||||
const lowercaseRegex = /[a-z]/
|
|
||||||
if (!lowercaseRegex.test(password)) {
|
|
||||||
result.errors.push('passwordError.noLowercase')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.hasLowercase = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 检查大写字母
|
|
||||||
const uppercaseRegex = /[A-Z]/
|
|
||||||
if (!uppercaseRegex.test(password)) {
|
|
||||||
result.errors.push('passwordError.noUppercase')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.hasUppercase = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 检查数字
|
|
||||||
const numberRegex = /[0-9]/
|
|
||||||
if (!numberRegex.test(password)) {
|
|
||||||
result.errors.push('passwordError.noNumber')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.hasNumber = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. 检查特殊字符
|
|
||||||
const specialCharRegex = /[\W_]/
|
|
||||||
if (!specialCharRegex.test(password)) {
|
|
||||||
result.errors.push('passwordError.noSpecialChar')
|
|
||||||
result.valid = false
|
|
||||||
} else {
|
|
||||||
result.details.hasSpecialChar = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实时校验密码强度(适用于input输入时)
|
|
||||||
* @param {string} password - 当前输入的密码
|
|
||||||
* @returns {Object} 强度分析结果
|
|
||||||
*/
|
|
||||||
export function checkPasswordStrength(password) {
|
|
||||||
const validation = validatePassword(password)
|
|
||||||
|
|
||||||
// 计算强度分数(0-100)
|
|
||||||
const maxScore = 6
|
|
||||||
const passedRules = Object.values(validation.details).filter(v => v).length
|
|
||||||
const score = Math.round((passedRules / maxScore) * 100)
|
|
||||||
|
|
||||||
// 强度等级
|
|
||||||
let level = 'weak'
|
|
||||||
if (score >= 85) level = 'strong'
|
|
||||||
else if (score >= 50) level = 'medium'
|
|
||||||
|
|
||||||
return {
|
|
||||||
score,
|
|
||||||
level,
|
|
||||||
validation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取友好的错误提示(用于Message组件)
|
|
||||||
* @param {Array<string>} errorKeys - 错误的i18n key数组
|
|
||||||
* @param {Function} t - vue-i18n的$t函数
|
|
||||||
* @returns {string} 格式化的错误提示文本
|
|
||||||
*/
|
|
||||||
export function formatPasswordErrors(errorKeys, t) {
|
|
||||||
if (!errorKeys || errorKeys.length === 0) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// 翻译所有错误信息
|
|
||||||
const errorMessages = errorKeys.map(key => t(key))
|
|
||||||
|
|
||||||
// 格式化为列表形式
|
|
||||||
if (errorMessages.length === 1) {
|
|
||||||
return errorMessages[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return errorMessages.map((msg, index) => `${index + 1}. ${msg}`).join('\n')
|
|
||||||
}
|
|
||||||
@@ -91,7 +91,7 @@ export const getImageUrl = (path) => {
|
|||||||
const baseUrl = process.env.VUE_APP_BASE_URL;
|
const baseUrl = process.env.VUE_APP_BASE_URL;
|
||||||
if (!path) return '';
|
if (!path) return '';
|
||||||
if (path.startsWith('http')) {
|
if (path.startsWith('http')) {
|
||||||
return path.replace('http://test.m2pool.com', baseUrl);
|
return path.replace('https://test.m2pool.com', baseUrl);
|
||||||
}
|
}
|
||||||
return `${baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
|
return `${baseUrl}${path.startsWith('/') ? '' : '/'}${path}`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,15 +2,6 @@ import axios from 'axios'
|
|||||||
import errorCode from './errorCode'
|
import errorCode from './errorCode'
|
||||||
import { Notification, MessageBox, Message } from 'element-ui'
|
import { Notification, MessageBox, Message } from 'element-ui'
|
||||||
import loadingManager from './loadingManager';
|
import loadingManager from './loadingManager';
|
||||||
import errorNotificationManager from './errorNotificationManager';
|
|
||||||
|
|
||||||
|
|
||||||
const pendingRequestMap = new Map(); //处理Request aborted 错误
|
|
||||||
|
|
||||||
function getRequestKey(config) { //处理Request aborted 错误 生成唯一 key 的函数
|
|
||||||
const { url, method, params, data } = config;
|
|
||||||
return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');
|
|
||||||
}
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||||
@@ -28,51 +19,10 @@ let lastNetworkErrorTime = 0; // 上次网络错误提示时间
|
|||||||
let pendingRequests = new Map();
|
let pendingRequests = new Map();
|
||||||
|
|
||||||
|
|
||||||
// 网络状态监听器
|
|
||||||
// 网络状态最后提示时间
|
|
||||||
let lastNetworkStatusTime = {
|
|
||||||
online: 0,
|
|
||||||
offline: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// 创建一个全局标志,确保每次网络恢复只显示一次提示
|
|
||||||
let networkRecoveryInProgress = false;
|
|
||||||
|
|
||||||
// 网络状态监听器
|
// 网络状态监听器
|
||||||
window.addEventListener('online', () => {
|
window.addEventListener('online', () => {
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
// 避免短时间内多次触发
|
|
||||||
if (networkRecoveryInProgress) {
|
|
||||||
console.log('[网络] 网络恢复处理已在进行中,忽略重复事件');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkRecoveryInProgress = true;
|
|
||||||
|
|
||||||
// 严格检查是否应该显示提示
|
|
||||||
if (now - lastNetworkStatusTime.online > 30000) { // 30秒内不重复提示
|
|
||||||
lastNetworkStatusTime.online = now;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (window.vm && window.vm.$message) {
|
|
||||||
// 确保消息只显示一次
|
|
||||||
window.vm.$message({
|
|
||||||
message: window.vm.$i18n.t('home.networkReconnected') || '网络已重新连接,正在恢复数据...',
|
|
||||||
type: 'success',
|
|
||||||
duration: 5000,
|
|
||||||
showClose: true,
|
|
||||||
});
|
|
||||||
console.log('[网络] 显示网络恢复提示, 时间:', new Date().toLocaleTimeString());
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[网络] 显示网络恢复提示失败:', e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('[网络] 抑制重复的网络恢复提示, 间隔过短:', now - lastNetworkStatusTime.online + 'ms');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 网络恢复时,重试所有待处理的请求
|
// 网络恢复时,重试所有待处理的请求
|
||||||
|
const now = Date.now();
|
||||||
const pendingPromises = [];
|
const pendingPromises = [];
|
||||||
|
|
||||||
pendingRequests.forEach(async (request, key) => {
|
pendingRequests.forEach(async (request, key) => {
|
||||||
@@ -121,62 +71,34 @@ window.addEventListener('online', () => {
|
|||||||
// 等待所有请求完成
|
// 等待所有请求完成
|
||||||
Promise.allSettled(pendingPromises).then(() => {
|
Promise.allSettled(pendingPromises).then(() => {
|
||||||
// 重置所有 loading 状态
|
// 重置所有 loading 状态
|
||||||
if (loadingManager) {
|
|
||||||
loadingManager.resetAllLoadingStates();
|
loadingManager.resetAllLoadingStates();
|
||||||
}
|
|
||||||
|
|
||||||
// 手动重置一些关键的 loading 状态
|
|
||||||
if (window.vm) {
|
|
||||||
// 常见的加载状态
|
|
||||||
const commonLoadingProps = [
|
|
||||||
'minerChartLoading', 'reportBlockLoading', 'apiPageLoading',
|
|
||||||
'MiningLoading', 'miniLoading', 'bthLoading', 'editLoading'
|
|
||||||
];
|
|
||||||
|
|
||||||
commonLoadingProps.forEach(prop => {
|
|
||||||
if (typeof window.vm[prop] !== 'undefined') {
|
|
||||||
window.vm[prop] = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重置所有以Loading结尾的状态
|
|
||||||
Object.keys(window.vm).forEach(key => {
|
|
||||||
if (key.endsWith('Loading')) {
|
|
||||||
window.vm[key] = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 触发网络重试完成事件
|
// 触发网络重试完成事件
|
||||||
window.dispatchEvent(new CustomEvent('network-retry-complete'));
|
window.dispatchEvent(new CustomEvent('network-retry-complete'));
|
||||||
|
|
||||||
// 重置网络恢复标志
|
|
||||||
setTimeout(() => {
|
|
||||||
networkRecoveryInProgress = false;
|
|
||||||
}, 5000); // 5秒后允许再次处理网络恢复
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用错误提示管理器控制网络断开提示
|
// 显示网络恢复提示
|
||||||
|
if (window.vm && window.vm.$message) {
|
||||||
|
window.vm.$message({
|
||||||
|
message: window.vm.$i18n.t('home.networkReconnected') || '网络已重新连接,正在恢复数据...',
|
||||||
|
type: 'success',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
window.addEventListener('offline', () => {
|
window.addEventListener('offline', () => {
|
||||||
if (window.vm && window.vm.$message && errorNotificationManager.canShowError('networkOffline')) {
|
if (window.vm && window.vm.$message) {
|
||||||
window.vm.$message({
|
window.vm.$message({
|
||||||
message: window.vm.$i18n.t('home.networkOffline') || '网络连接已断开,系统将在恢复连接后自动重试',
|
message: window.vm.$i18n.t('home.networkOffline') || '网络连接已断开,系统将在恢复连接后自动重试',
|
||||||
type: 'error',
|
type: 'warning',
|
||||||
duration: 5000,
|
duration: 3000
|
||||||
showClose: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
service.defaults.retry = 2;// 重试次数
|
service.defaults.retry = 2;// 重试次数
|
||||||
service.defaults.retryDelay = 2000;
|
service.defaults.retryDelay = 2000;
|
||||||
service.defaults.shouldRetry = (error) => {
|
service.defaults.shouldRetry = (error) => true
|
||||||
// 只有网络错误或超时错误才进行重试
|
|
||||||
return error.message === "Network Error" || error.message.includes("timeout");
|
|
||||||
};
|
|
||||||
|
|
||||||
localStorage.setItem('superReportError', "")
|
localStorage.setItem('superReportError', "")
|
||||||
let superReportError = localStorage.getItem('superReportError')
|
let superReportError = localStorage.getItem('superReportError')
|
||||||
@@ -228,22 +150,6 @@ service.interceptors.request.use(config => {
|
|||||||
config.params = {};
|
config.params = {};
|
||||||
config.url = url;
|
config.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成请求唯一key 处理Request aborted 错误
|
|
||||||
const requestKey = getRequestKey(config);
|
|
||||||
|
|
||||||
// 如果有相同请求,先取消 处理Request aborted 错误
|
|
||||||
if (pendingRequestMap.has(requestKey)) {
|
|
||||||
const cancel = pendingRequestMap.get(requestKey);
|
|
||||||
cancel(); // 取消上一次请求
|
|
||||||
pendingRequestMap.delete(requestKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建新的CancelToken 处理Request aborted 错误
|
|
||||||
config.cancelToken = new axios.CancelToken(cancel => {
|
|
||||||
pendingRequestMap.set(requestKey, cancel);
|
|
||||||
});
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}, error => {
|
}, error => {
|
||||||
Promise.reject(error)
|
Promise.reject(error)
|
||||||
@@ -251,16 +157,11 @@ service.interceptors.request.use(config => {
|
|||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
service.interceptors.response.use(res => {
|
service.interceptors.response.use(res => {
|
||||||
|
|
||||||
// 请求完成后移除
|
|
||||||
const requestKey = getRequestKey(res.config);
|
|
||||||
pendingRequestMap.delete(requestKey);
|
|
||||||
// 未设置状态码则默认成功状态
|
// 未设置状态码则默认成功状态
|
||||||
const code = res.data.code || 200;
|
const code = res.data.code || 200;
|
||||||
// 获取错误信息
|
// 获取错误信息
|
||||||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
||||||
if (code === 421) {
|
if (code === 421) {
|
||||||
localStorage.setItem('cs_disconnect_all', Date.now().toString()); //告知客服页面断开连接
|
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
// 系统状态已过期,请重新点击SUPPORT按钮进入
|
// 系统状态已过期,请重新点击SUPPORT按钮进入
|
||||||
superReportError = localStorage.getItem('superReportError')
|
superReportError = localStorage.getItem('superReportError')
|
||||||
@@ -277,10 +178,10 @@ service.interceptors.response.use(res => {
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
}
|
}
|
||||||
).then(() => {
|
).then(() => {
|
||||||
window.vm.$router.push(`/${window.vm.$i18n.locale}/login`)
|
window.vm.$router.push("/login")
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
window.vm.$router.push(`/${window.vm.$i18n.locale}/`)
|
window.vm.$router.push("/")
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -319,27 +220,11 @@ service.interceptors.response.use(res => {
|
|||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
|
|
||||||
// 主动取消的请求,直接忽略,不提示
|
|
||||||
if (
|
|
||||||
error.code === 'ERR_CANCELED' ||
|
|
||||||
(error.message && error.message.includes('canceled')) ||
|
|
||||||
error.message?.includes('Request aborted')
|
|
||||||
) {
|
|
||||||
// 静默处理,不提示,不冒泡
|
|
||||||
return new Promise(() => {}); // 返回pending Promise,阻止控制台报错
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 请求异常也要移除 处理Request aborted 错误
|
|
||||||
if (error.config) {
|
|
||||||
const requestKey = getRequestKey(error.config);
|
|
||||||
pendingRequestMap.delete(requestKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let { message } = error;
|
let { message } = error;
|
||||||
|
|
||||||
if (message == "Network Error" || message.includes("timeout")) {
|
if (message == "Network Error" || message.includes("timeout")) {
|
||||||
if (!navigator.onLine) {
|
if (!navigator.onLine) {
|
||||||
// 断网状态,添加到重试队列
|
// 断网状态,添加到重试队列
|
||||||
@@ -377,37 +262,30 @@ service.interceptors.response.use(res => {
|
|||||||
|
|
||||||
console.log('请求已加入断网重连队列:', error.config.url);
|
console.log('请求已加入断网重连队列:', error.config.url);
|
||||||
}
|
}
|
||||||
} else {
|
} else if ((error.config.retry > 0 && error.config)) {
|
||||||
// 网络已连接,但请求失败,尝试重试
|
// 保留现有的重试逻辑
|
||||||
// 确保 config 中有 __retryCount 字段
|
error.config.retry--;
|
||||||
error.config.__retryCount = error.config.__retryCount || 0;
|
|
||||||
|
|
||||||
// 判断是否可以重试
|
|
||||||
if (error.config.__retryCount < service.defaults.retry && service.defaults.shouldRetry(error)) {
|
|
||||||
// 增加重试计数
|
|
||||||
error.config.__retryCount += 1;
|
|
||||||
|
|
||||||
console.log(`[请求重试] ${error.config.url} - 第 ${error.config.__retryCount} 次重试`);
|
|
||||||
|
|
||||||
// 创建新的Promise等待一段时间后重试
|
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve(service(error.config));
|
resolve(service(error.config));
|
||||||
}, service.defaults.retryDelay);
|
}, 2000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 达到最大重试次数,不再重试
|
|
||||||
console.log(`[请求失败] ${error.config.url} - 已达到最大重试次数`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!superReportError) {
|
if (!superReportError) {
|
||||||
superReportError = "error"
|
superReportError = "error"
|
||||||
localStorage.setItem('superReportError', superReportError)
|
localStorage.setItem('superReportError', superReportError)
|
||||||
//使用错误提示管理器errorNotificationManager
|
let { message } = error;
|
||||||
if (errorNotificationManager.canShowError(message)) {
|
|
||||||
if (message == "Network Error") {
|
if (message == "Network Error") {
|
||||||
|
// message = "后端接口网络连接异常,请刷新重试";
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - lastNetworkErrorTime > NETWORK_ERROR_THROTTLE_TIME) {
|
||||||
|
lastNetworkErrorTime = now; // 更新最后提示时间
|
||||||
Message({
|
Message({
|
||||||
message: window.vm.$i18n.t(`home.NetworkError`),
|
message: window.vm.$i18n.t(`home.NetworkError`),
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -415,38 +293,42 @@ service.interceptors.response.use(res => {
|
|||||||
showClose: true
|
showClose: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else if (message.includes("timeout")) {
|
else if (message.includes("timeout")) {
|
||||||
|
// message = "系统接口请求超时,请刷新重试";
|
||||||
Message({
|
Message({
|
||||||
message: window.vm.$i18n.t(`home.requestTimeout`),
|
message: window.vm.$i18n.t(`home.requestTimeout`),
|
||||||
type: 'error',
|
type: 'error',
|
||||||
duration: 5 * 1000,
|
duration: 5 * 1000,
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (message.includes("Request failed with status code")) {
|
else if (message.includes("Request failed with status code")) {
|
||||||
|
// message = "系统接口" + message.substr(message.length - 3) + "异常";
|
||||||
Message({
|
Message({
|
||||||
message: "系统接口" + message.substr(message.length - 3) + "异常",
|
message: "系统接口" + message.substr(message.length - 3) + "异常",
|
||||||
type: 'error',
|
type: 'error',
|
||||||
duration: 5 * 1000,
|
duration: 5 * 1000,
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Message({
|
Message({
|
||||||
message: message,
|
message: message,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
duration: 5 * 1000,
|
duration: 5 * 1000,
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
})
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 避免完全不提示,可以在控制台记录被抑制的错误
|
|
||||||
console.log('[错误提示] 已抑制重复错误:', message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
//自动记录请求参数,并支持断网重连,创建一个函数装饰器
|
|
||||||
/**
|
|
||||||
* 包装请求方法,自动注册断网重连恢复
|
|
||||||
* @param {Object} component - 组件实例
|
|
||||||
* @param {String} methodName - 方法名
|
|
||||||
* @param {Function} originalMethod - 原始方法
|
|
||||||
* @returns {Function} 包装后的方法
|
|
||||||
*/
|
|
||||||
export function wrapRequestMethod(component, methodName, originalMethod) {
|
|
||||||
return async function(...args) {
|
|
||||||
// 注册为恢复方法(仅当组件支持断网重连恢复)
|
|
||||||
if (component.registerRecoveryMethod) {
|
|
||||||
component.registerRecoveryMethod(methodName, args[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用原始方法
|
|
||||||
return await originalMethod.apply(component, args);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自动包装组件中的所有请求方法
|
|
||||||
* @param {Object} component - 组件实例
|
|
||||||
* @param {Array<String>} methodNames - 方法名列表
|
|
||||||
*/
|
|
||||||
export function wrapComponentMethods(component, methodNames) {
|
|
||||||
methodNames.forEach(methodName => {
|
|
||||||
if (typeof component[methodName] === 'function') {
|
|
||||||
const originalMethod = component[methodName];
|
|
||||||
component[methodName] = wrapRequestMethod(component, methodName, originalMethod);
|
|
||||||
console.log(`[RequestWrapper] 包装方法: ${methodName}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
/**
|
|
||||||
* 路由工具函数
|
|
||||||
* 用于获取项目中所有有效的路由路径
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取所有有效的路由路径
|
|
||||||
* @returns {Array} 有效路径数组
|
|
||||||
*/
|
|
||||||
export function getAllValidPaths() {
|
|
||||||
const validPaths = [
|
|
||||||
// 主要页面路径
|
|
||||||
'/',
|
|
||||||
'/home',
|
|
||||||
'/miningAccount',
|
|
||||||
'/readOnlyDisplay',
|
|
||||||
'/reportBlock',
|
|
||||||
'/broadcast',
|
|
||||||
'/userManagement',
|
|
||||||
'/userDetails',
|
|
||||||
'/rate',
|
|
||||||
'/allocationExplanation',
|
|
||||||
'/apiFile',
|
|
||||||
'/customerService',
|
|
||||||
'/ServiceTerms',
|
|
||||||
'/submitWorkOrder',
|
|
||||||
'/workOrderRecords',
|
|
||||||
'/userWorkDetails',
|
|
||||||
'/workOrderBackend',
|
|
||||||
'/BKWorkDetails',
|
|
||||||
'/dataDisplay',
|
|
||||||
'/alerts',
|
|
||||||
'/helpCenter',
|
|
||||||
'/commonProblem',
|
|
||||||
'/announcementDetails',
|
|
||||||
'/searchResult',
|
|
||||||
'/announcements',
|
|
||||||
'/announcementDetails',
|
|
||||||
|
|
||||||
// 个人中心子页面
|
|
||||||
'/personalCenter',
|
|
||||||
'/personalCenter/personalMining',
|
|
||||||
'/personalCenter/readOnly',
|
|
||||||
'/personalCenter/securitySetting',
|
|
||||||
'/personalCenter/personal',
|
|
||||||
'/personalCenter/miningReport',
|
|
||||||
'/personalCenter/personalAPI',
|
|
||||||
|
|
||||||
// 接入矿池页面
|
|
||||||
'/AccessMiningPool',
|
|
||||||
'/AccessMiningPool/nexaAccess',
|
|
||||||
'/AccessMiningPool/rxdAccess',
|
|
||||||
'/AccessMiningPool/monaAccess',
|
|
||||||
'/AccessMiningPool/grsAccess',
|
|
||||||
'/AccessMiningPool/dgbqAccess',
|
|
||||||
'/AccessMiningPool/dgboAccess',
|
|
||||||
'/AccessMiningPool/dgbsAccess',
|
|
||||||
// '/AccessMiningPool/enxAccess',
|
|
||||||
'/AccessMiningPool/alphminingPool',
|
|
||||||
|
|
||||||
// 独立页面
|
|
||||||
'/login',
|
|
||||||
'/register',
|
|
||||||
'/simulation',
|
|
||||||
'/resetPassword',
|
|
||||||
'/404'
|
|
||||||
];
|
|
||||||
|
|
||||||
return validPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证路径是否有效
|
|
||||||
* @param {string} path - 要验证的路径
|
|
||||||
* @returns {boolean} 是否为有效路径
|
|
||||||
*/
|
|
||||||
export function isValidPath(path) {
|
|
||||||
if (!path || typeof path !== 'string') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const trimmedPath = path.trim();
|
|
||||||
|
|
||||||
// 主页路径的特殊处理
|
|
||||||
if (trimmedPath === '/' || trimmedPath === '') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 去除开头的斜杠进行标准化
|
|
||||||
const normalizedPath = trimmedPath.startsWith('/') ? trimmedPath.substring(1) : trimmedPath;
|
|
||||||
|
|
||||||
const validPaths = getAllValidPaths();
|
|
||||||
|
|
||||||
// 检查标准化路径是否匹配
|
|
||||||
const pathsWithoutSlash = validPaths.map(p => p.replace(/^\//, '')).filter(p => p !== '');
|
|
||||||
|
|
||||||
return pathsWithoutSlash.includes(normalizedPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取路径建议列表(用于错误提示或自动完成)
|
|
||||||
* @param {string} input - 用户输入的路径
|
|
||||||
* @returns {Array} 建议的路径列表
|
|
||||||
*/
|
|
||||||
export function getPathSuggestions(input) {
|
|
||||||
if (!input) {
|
|
||||||
return getAllValidPaths().slice(0, 10); // 返回前10个路径作为建议
|
|
||||||
}
|
|
||||||
|
|
||||||
const validPaths = getAllValidPaths();
|
|
||||||
const normalizedInput = input.toLowerCase().trim();
|
|
||||||
|
|
||||||
// 查找包含输入内容的路径
|
|
||||||
return validPaths.filter(path =>
|
|
||||||
path.toLowerCase().includes(normalizedInput)
|
|
||||||
).slice(0, 5); // 最多返回5个建议
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { findDataInfo ,documentsList} from '../../api/documentManagement'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -222,19 +223,19 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: "enxAccess",
|
path: "enxAccess",
|
||||||
// value: "enx",
|
value: "enx",
|
||||||
// label: "Entropyx(enx)",
|
label: "Entropyx(enx)",
|
||||||
// imgUrl:`${this.$baseApi}img/enx.svg`,
|
imgUrl:`${this.$baseApi}img/enx.svg`,
|
||||||
// show: true,
|
show: true,
|
||||||
// name: "course.ENXcourse",
|
name: "course.ENXcourse",
|
||||||
// amount: 5000,
|
amount: 5000,
|
||||||
// tcp: "",
|
tcp: "",
|
||||||
// ssl: ""
|
ssl: ""
|
||||||
|
|
||||||
|
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
path: "alphminingPool",
|
path: "alphminingPool",
|
||||||
value: "alph",
|
value: "alph",
|
||||||
@@ -256,22 +257,6 @@ export default {
|
|||||||
imgUrl: `${this.$baseApi}img/nexa.png`,
|
imgUrl: `${this.$baseApi}img/nexa.png`,
|
||||||
activeName: "1",
|
activeName: "1",
|
||||||
currentRoutePath:"",
|
currentRoutePath:"",
|
||||||
|
|
||||||
listParams:{
|
|
||||||
type:"1",//挖矿教程
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:50
|
|
||||||
},
|
|
||||||
tutorialLoading:false,
|
|
||||||
navList:[],
|
|
||||||
DetailsParams:{
|
|
||||||
id:"",
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
},
|
|
||||||
info:"",
|
|
||||||
activeId:"",
|
|
||||||
contentShow:false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -284,8 +269,8 @@ export default {
|
|||||||
this.currentRoutePath =to.path.split(`/`)[3]
|
this.currentRoutePath =to.path.split(`/`)[3]
|
||||||
|
|
||||||
|
|
||||||
// this.activeItem = this.currencyList.find(item => { return item.path == this.currentRoutePath })
|
this.activeItem = this.currencyList.find(item => { return item.path == this.currentRoutePath })
|
||||||
// this.$addStorageEvent(1, `activeItem`, JSON.stringify( this.activeItem))
|
this.$addStorageEvent(1, `activeItem`, JSON.stringify( this.activeItem))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -294,74 +279,90 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
// 优先级:路由参数 > localStorage > 默认
|
|
||||||
let coinFromRoute = this.$route.params && this.$route.params.coin;
|
|
||||||
let localActiveCoin = localStorage.getItem('activeCoin') ? JSON.parse(localStorage.getItem('activeCoin')) : null;
|
|
||||||
let targetCoin = coinFromRoute || localActiveCoin || (this.currencyList[0] && this.currencyList[0].value);
|
|
||||||
|
|
||||||
this.activeCoin = targetCoin;
|
if (this.$route.name =="AccessMiningPool" ) {
|
||||||
this.activeItem = this.currencyList.find(item => item.value === targetCoin) || this.currencyList[0];
|
this.$router.go(-1);
|
||||||
this.params.coin = targetCoin;
|
|
||||||
|
|
||||||
// 如果是路由参数,记忆到localStorage
|
|
||||||
if (coinFromRoute) {
|
|
||||||
localStorage.setItem('activeCoin', JSON.stringify(coinFromRoute));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetchAllList(this.listParams);
|
|
||||||
|
|
||||||
|
if (this.$route.params.coin) {
|
||||||
|
this.activeCoin = this.$route.params.coin
|
||||||
|
// this.currencyPath = this.$route.query.imgUrl
|
||||||
|
this.imgUrl = this.$route.params.imgUrl
|
||||||
|
this.currencyPath = this.$route.params.imgUrl
|
||||||
|
this.params.coin = this.$route.params.coin
|
||||||
|
this.$addStorageEvent(1, `activeCoin`, JSON.stringify(this.activeCoin))
|
||||||
|
this.activeItem = this.currencyList.find(item => { return item.value == this.params.coin })
|
||||||
|
const item = this.currencyList.find(item => { return item.value == this.params.coin })
|
||||||
|
|
||||||
|
if (item && item.path) {
|
||||||
|
// this.clickJump(item)
|
||||||
|
const mockEvent = {
|
||||||
|
stopPropagation: () => {},
|
||||||
|
currentTarget: document.getElementById('menu1')
|
||||||
|
};
|
||||||
|
this.changeMenuName(mockEvent, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let activeCoin = localStorage.getItem("activeCoin")
|
||||||
|
this.activeCoin = JSON.parse(activeCoin)
|
||||||
|
let currencyList = localStorage.getItem("currencyList")
|
||||||
|
this.currencyList = JSON.parse(currencyList)
|
||||||
|
window.addEventListener("setItem", () => {
|
||||||
|
let activeCoin = localStorage.getItem("activeCoin")
|
||||||
|
this.activeCoin = JSON.parse(activeCoin)
|
||||||
|
let currencyList = localStorage.getItem("currencyList")
|
||||||
|
this.currencyList = JSON.parse(currencyList)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!this.activeCoin) {
|
||||||
|
this.activeCoin = "nexa"
|
||||||
|
this.imgUrl = `https://test.m2pool.com/img/nexa.png`
|
||||||
|
this.currencyPath = `https://test.m2pool.com/img/nexa.png`
|
||||||
|
this.params.coin = "nexa"
|
||||||
|
this.$addStorageEvent(1, `activeCoin`, JSON.stringify(this.activeCoin))
|
||||||
|
this.openAPI = true
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// this.openAPI =true
|
||||||
|
try {
|
||||||
|
this.pageTitle = this.currencyList.find(item => item.value == this.activeCoin).name
|
||||||
|
this.imgUrl = this.currencyList.find(item => item.value == this.activeCoin).imgUrl
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// 从本地存储获取activeItem
|
||||||
|
const savedActiveItem = localStorage.getItem('activeItem');
|
||||||
|
if (savedActiveItem) {
|
||||||
|
try {
|
||||||
|
this.activeItem = JSON.parse(savedActiveItem);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Parse activeItem failed:', error);
|
||||||
|
// 使用默认值
|
||||||
|
this.activeItem = this.currencyList[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有存储值时使用默认值
|
||||||
|
this.activeItem = this.currencyList[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchAllList(params){
|
|
||||||
this.setLoading('tutorialLoading', true);
|
|
||||||
const res = await documentsList(params)
|
|
||||||
console.log(res,"res");
|
|
||||||
|
|
||||||
if (res && res.code === 200) {
|
|
||||||
// 按照id升序排序,确保最小id在最上面
|
|
||||||
const sortedRows = (res.rows || []).slice().sort((a, b) => Number(a.id) - Number(b.id))
|
|
||||||
this.navList = sortedRows
|
|
||||||
|
|
||||||
const item = this.navList.find(item => { return item.coin == this.params.coin })
|
|
||||||
|
|
||||||
|
|
||||||
if (item && item.coin) {
|
|
||||||
this.DetailsParams.id= item.id
|
|
||||||
this.DetailsParams.coin = item.coin
|
|
||||||
this.clickJump(item)
|
|
||||||
|
|
||||||
}else if (this.$route.query.id) {
|
|
||||||
this.DetailsParams.id = this.$route.query.id
|
|
||||||
|
|
||||||
}else{
|
|
||||||
this.DetailsParams.id = this.navList[0] && this.navList[0].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.DetailsParams.id) {
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchProblemDetails(params) {
|
|
||||||
this.setLoading('tutorialLoading', true);
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
this.activeId = res.data.id
|
|
||||||
this.contentShow = true
|
|
||||||
}
|
|
||||||
this.setLoading('tutorialLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
backMenu(){
|
|
||||||
this.contentShow = false
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// isActiveRoute(item) {
|
// isActiveRoute(item) {
|
||||||
// // 直接使用完整的路径进行比较
|
// // 直接使用完整的路径进行比较
|
||||||
// return this.currentRoutePath.includes(`AccessMiningPool/${item.path}`);
|
// return this.currentRoutePath.includes(`AccessMiningPool/${item.path}`);
|
||||||
@@ -379,7 +380,6 @@ export default {
|
|||||||
},
|
},
|
||||||
changeMenuName(e, item) {
|
changeMenuName(e, item) {
|
||||||
|
|
||||||
console.log(`走移动端了?`);
|
|
||||||
|
|
||||||
|
|
||||||
if (!e) return;
|
if (!e) return;
|
||||||
@@ -413,25 +413,18 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
clickJump(item) {
|
clickJump(item) {
|
||||||
|
if (!item.path) return; // 添加路径检查
|
||||||
this.DetailsParams.id = item.id
|
this.activeCoin = item.value
|
||||||
this.DetailsParams.coin = item.coin
|
this.pageTitle = item.name
|
||||||
this.activeCoin = item.coin
|
this.imgUrl = item.imgUrl
|
||||||
localStorage.setItem('activeCoin', JSON.stringify(this.activeCoin))
|
this.$addStorageEvent(1, `activeCoin`, JSON.stringify(item.value))
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
// this.$router.push(item.url)
|
||||||
|
const lang = this.$i18n.locale;
|
||||||
// if (!item.path) return; // 添加路径检查
|
this.$router.push(`/${lang}/AccessMiningPool/${item.path}`).catch(err => {
|
||||||
// this.activeCoin = item.value
|
if (err.name !== 'NavigationDuplicated') {
|
||||||
// this.pageTitle = item.name
|
console.error('Navigation failed:', err);
|
||||||
// this.imgUrl = item.imgUrl
|
}
|
||||||
// this.$addStorageEvent(1, `activeCoin`, JSON.stringify(item.value))
|
});
|
||||||
// // this.$router.push(item.url)
|
|
||||||
// const lang = this.$i18n.locale;
|
|
||||||
// this.$router.push(`/${lang}/AccessMiningPool/${item.path}`).catch(err => {
|
|
||||||
// if (err.name !== 'NavigationDuplicated') {
|
|
||||||
// console.error('Navigation failed:', err);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="AccessMiningPoolMain" v-loading="tutorialLoading">
|
<div class="AccessMiningPoolMain">
|
||||||
<section v-if="openAPI" class="openAPI">
|
<section v-if="openAPI" class="openAPI">
|
||||||
<section v-if="$isMobile">
|
<section v-if="$isMobile">
|
||||||
<!-- <div class="currencySelect">
|
<div class="currencySelect">
|
||||||
|
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<div class="nav-item" id="menu1" @click.stop="toggleDropdown">
|
<div class="nav-item" id="menu1" @click.stop="toggleDropdown">
|
||||||
<img
|
<img
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
:key="item.value"
|
:key="item.value"
|
||||||
@click.stop="changeMenuName($event, item)"
|
@click.stop="changeMenuName($event, item)"
|
||||||
:class="{ optionActive: $route.path.includes(item.path) }"
|
:class="{ optionActive: $route.path.includes(item.path) }"
|
||||||
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="dropdownCoin"
|
class="dropdownCoin"
|
||||||
@@ -32,68 +34,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
|
|
||||||
<section class="menu2" v-if="!contentShow">
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
:class="{ active: activeCoin == item.coin }"
|
|
||||||
@click="clickJump(item)"
|
|
||||||
v-for="item in navList"
|
|
||||||
:key="item.id"
|
|
||||||
>
|
|
||||||
<img class="img2" :src="item.titleUrl" alt="coin" />
|
|
||||||
<span>
|
|
||||||
{{ item.title }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
<!--
|
|
||||||
<section>
|
<section>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<router-view :key="$route.fullPath" />
|
<router-view :key="$route.fullPath" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</section> -->
|
|
||||||
|
|
||||||
<!-- 显示内容 -->
|
|
||||||
<section class="tutorialContent" v-else>
|
|
||||||
<p class="backMenu" @click="backMenu">{{ $t("course.backMenu") || "返回挖矿教程目录" }} </p>
|
|
||||||
<section class="rightContent">
|
|
||||||
<div v-if="tutorialLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{
|
|
||||||
$t("home.loadingContent") || "正在加载内容..."
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="info && info.trim()"
|
|
||||||
class="dynamic-content"
|
|
||||||
v-html="info"
|
|
||||||
></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t("home.noContent") || "暂无内容" }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- <router-view></router-view> -->
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="AccessMiningPool" v-else>
|
<section class="AccessMiningPool" v-else>
|
||||||
|
|
||||||
|
|
||||||
<section class="menu">
|
<section class="menu">
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
:class="{ active: activeCoin == item.coin }"
|
|
||||||
@click="clickJump(item)"
|
|
||||||
v-for="item in navList"
|
|
||||||
:key="item.id"
|
|
||||||
>
|
|
||||||
<img :src="item.titleUrl" alt="coin" />
|
|
||||||
<span>
|
|
||||||
{{ item.title }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<!-- <li
|
|
||||||
|
|
||||||
:class="{ active: currentRoutePath == item.path }"
|
:class="{ active: currentRoutePath == item.path }"
|
||||||
@click="clickJump(item)"
|
@click="clickJump(item)"
|
||||||
@@ -104,27 +60,11 @@
|
|||||||
<span>
|
<span>
|
||||||
{{ $t(item.name) }}
|
{{ $t(item.name) }}
|
||||||
</span>
|
</span>
|
||||||
</li> -->
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section class="tutorialContent">
|
<section class="tutorialContent">
|
||||||
<section class="rightContent">
|
<router-view></router-view>
|
||||||
<div v-if="tutorialLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{
|
|
||||||
$t("home.loadingContent") || "正在加载内容..."
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="info && info.trim()"
|
|
||||||
class="dynamic-content"
|
|
||||||
v-html="info"
|
|
||||||
></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t("home.noContent") || "暂无内容" }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- <router-view></router-view> -->
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
@@ -151,7 +91,7 @@ export default {
|
|||||||
$route(to, from) {
|
$route(to, from) {
|
||||||
// 监听路由变化,处理组件更新
|
// 监听路由变化,处理组件更新
|
||||||
this.handleRouteChange(to, from);
|
this.handleRouteChange(to, from);
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleRouteChange(to, from) {
|
handleRouteChange(to, from) {
|
||||||
@@ -180,7 +120,7 @@ export default {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -199,141 +139,10 @@ export default {
|
|||||||
padding-top: 30px;
|
padding-top: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow-y: auto;
|
|
||||||
height: 100%;
|
|
||||||
.mail {
|
.mail {
|
||||||
color: #5917c4;
|
color: #5917c4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 移动端内容卡片与正文区域适配 */
|
|
||||||
.tutorialContent {
|
|
||||||
width: 98% !important; /* 贴近屏幕但保留安全间距 */
|
|
||||||
padding: 0 !important;
|
|
||||||
margin: 0 auto !important;
|
|
||||||
box-shadow: 0 0 6px 1px rgba(0, 0, 0, 0.08) !important;
|
|
||||||
border-radius: 8px !important;
|
|
||||||
background: transparent !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
.backMenu{
|
|
||||||
color: #6924ff;
|
|
||||||
font-size: 0.95rem !important;
|
|
||||||
margin: 0 0 10px 2px !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.rightContent {
|
|
||||||
margin-left: 0 !important; /* 取消桌面端的左侧外边距 */
|
|
||||||
padding: 6px !important; /* 适度内边距 */
|
|
||||||
// padding-right: 12px !important;
|
|
||||||
overflow-x: hidden !important;
|
|
||||||
font-size: 0.9rem !important; /* 移动端统一字号 */
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
/* 返回目录按钮在移动端的点击区域与排版 */
|
|
||||||
.backMenu {
|
|
||||||
font-size: 0.95rem !important;
|
|
||||||
margin: 0 0 10px 2px !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 富文本内容在移动端的表格适配:固定布局+自动换行 */
|
|
||||||
.rightContent .dynamic-content {
|
|
||||||
overflow-x: auto !important; /* 超出时允许横向滚动(兜底) */
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(table) {
|
|
||||||
/* 对含有 colspan/rowspan 的表格,固定布局会引发表头与列错位,这里改为自动布局 */
|
|
||||||
table-layout: auto !important;
|
|
||||||
width: 100% !important;
|
|
||||||
border-collapse: collapse !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(th) {//表格表头字号
|
|
||||||
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
word-break: break-word !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* 表格单元格字号 */
|
|
||||||
.rightContent .dynamic-content :deep(th),
|
|
||||||
.rightContent .dynamic-content :deep(td) {
|
|
||||||
word-break: break-word !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
padding: 2px !important;
|
|
||||||
font-size: 0.7rem !important; /* 表格单元格字号 */
|
|
||||||
min-width: 0 !important; /* 覆盖外层全局 td 的最小宽度,避免小屏列被强撑导致错位 */
|
|
||||||
vertical-align: left !important;
|
|
||||||
}
|
|
||||||
/* 步骤里的段落在移动端必须自动换行,禁止引发横向滚动条 */
|
|
||||||
.rightContent .dynamic-content :deep(p) {
|
|
||||||
max-width: 100% !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: break-word !important; /* 优先按单词/字符断行 */
|
|
||||||
overflow-wrap: anywhere !important; /* 极端长串也强制换行 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(a) {
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(li) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(pre) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(font) {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
min-width: 40px !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(h2) {
|
|
||||||
font-size: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(h3) {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.img2{
|
|
||||||
width: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu2{
|
|
||||||
max-height: 100vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
background: transparent !important;
|
|
||||||
ul{
|
|
||||||
padding: 18px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
li{
|
|
||||||
padding: 8px;
|
|
||||||
text-decoration: underline;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.active{
|
|
||||||
background: transparent !important;
|
|
||||||
color: rgba(0,0,0,1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.notOpen {
|
.notOpen {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
@@ -664,7 +473,7 @@ export default {
|
|||||||
|
|
||||||
.AccessMiningPoolMain {
|
.AccessMiningPoolMain {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
// height: 100vh;
|
||||||
}
|
}
|
||||||
.openAPI {
|
.openAPI {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -695,12 +504,6 @@ export default {
|
|||||||
box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.1);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #fff;
|
|
||||||
padding-top: 30px;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 20px;
|
|
||||||
padding-bottom: 30px;
|
|
||||||
}
|
}
|
||||||
.notOpen {
|
.notOpen {
|
||||||
// background: palegoldenrod;
|
// background: palegoldenrod;
|
||||||
@@ -739,9 +542,6 @@ export default {
|
|||||||
align-items:start;
|
align-items:start;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: left;
|
|
||||||
img {
|
img {
|
||||||
width: 25px;
|
width: 25px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
@@ -936,102 +736,4 @@ export default {
|
|||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rightContent {
|
|
||||||
flex: 1;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 50px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 20px;
|
|
||||||
background: #fff;
|
|
||||||
.dynamic-content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.7;
|
|
||||||
color: #222;
|
|
||||||
// 富文本样式
|
|
||||||
:deep(table) {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(th),
|
|
||||||
:deep(td) {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
:deep(th) {
|
|
||||||
background: #d2c3ea;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
:deep(strong),
|
|
||||||
:deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
:deep(em),
|
|
||||||
:deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
:deep(a) {
|
|
||||||
color: #661ffb !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:deep(p) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
text-indent: 0 !important;
|
|
||||||
line-height: 2 !important;
|
|
||||||
margin: 0.8em 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
:deep(div) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: 2 !important;
|
|
||||||
margin: 0.8em 0 !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-container {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
.loading-text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.no-content {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #999;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -73,12 +73,13 @@ export default {
|
|||||||
this.activeCoin= JSON.parse(activeCoin)
|
this.activeCoin= JSON.parse(activeCoin)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(this.activeCoin,"鸡脚低端局");
|
||||||
|
|
||||||
|
|
||||||
if ( !this.activeCoin ) {
|
if ( !this.activeCoin ) {
|
||||||
this.activeCoin ="nexa"
|
this.activeCoin ="nexa"
|
||||||
this.imgUrl = `${this.$baseApi}/img/nexa.png`
|
this.imgUrl = `https://test.m2pool.com/img/nexa.png`
|
||||||
this.currencyPath= `${this.$baseApi}/img/nexa.png`
|
this.currencyPath= `https://test.m2pool.com/img/nexa.png`
|
||||||
this.params.coin ="nexa"
|
this.params.coin ="nexa"
|
||||||
this.$addStorageEvent(1,`activeCoin`,JSON.stringify(this.activeCoin))
|
this.$addStorageEvent(1,`activeCoin`,JSON.stringify(this.activeCoin))
|
||||||
this.openAPI =true
|
this.openAPI =true
|
||||||
|
|||||||
@@ -171,13 +171,10 @@ export default {
|
|||||||
// this.stateList = JSON.parse(localStorage.getItem('stateList') )
|
// this.stateList = JSON.parse(localStorage.getItem('stateList') )
|
||||||
// this.typeList = JSON.parse(localStorage.getItem('typeList') )
|
// this.typeList = JSON.parse(localStorage.getItem('typeList') )
|
||||||
|
|
||||||
this.registerRecoveryMethod('fetchTicketDetails', { id: this.workOrderId });
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchBKendTicket(params){
|
async fetchBKendTicket(params){
|
||||||
// this.totalDetailsLoading =true
|
this.totalDetailsLoading =true
|
||||||
this.setLoading('totalDetailsLoading', true);
|
|
||||||
const data = await getBKendTicket(params)
|
const data = await getBKendTicket(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -188,12 +185,11 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('totalDetailsLoading', false);
|
this.totalDetailsLoading =false
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchReply(params){
|
async fetchReply(params){
|
||||||
// this.totalDetailsLoading = true
|
this.totalDetailsLoading = true
|
||||||
this.setLoading('totalDetailsLoading', true);
|
|
||||||
const data = await getReply(params)
|
const data = await getReply(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -209,7 +205,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('totalDetailsLoading', false);
|
this.totalDetailsLoading = false
|
||||||
},
|
},
|
||||||
handelType2(label){
|
handelType2(label){
|
||||||
if (label) {
|
if (label) {
|
||||||
@@ -235,15 +231,14 @@ export default {
|
|||||||
},
|
},
|
||||||
//请求工单详情
|
//请求工单详情
|
||||||
async fetchTicketDetails(param) {
|
async fetchTicketDetails(param) {
|
||||||
// this.totalDetailsLoading = true
|
this.totalDetailsLoading = true
|
||||||
this.setLoading('totalDetailsLoading', true);
|
|
||||||
const { data } = await getDetails(param)
|
const { data } = await getDetails(param)
|
||||||
|
|
||||||
this.recordList = data.list
|
this.recordList = data.list
|
||||||
this.ticketDetails = data
|
this.ticketDetails = data
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('totalDetailsLoading', false);
|
this.totalDetailsLoading = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -422,26 +422,21 @@ export default {
|
|||||||
}
|
}
|
||||||
.main {
|
.main {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: 100vh;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
// background-image: url(../../assets/img/miningAccount/top.png);
|
background-image: url(../../assets/img/miningAccount/top.png);
|
||||||
// background-size: 100% 50%;
|
background-size: 100% 50%;
|
||||||
// background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
// background-position: 30% -15%;
|
background-position: 30% -15%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
// padding-top: 60PX;
|
padding-top: 60PX;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
.content{
|
.content{
|
||||||
width: 100%;
|
width: 50%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.elBtn{
|
.elBtn{
|
||||||
background: #661FFB;
|
background: #661FFB;
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { documentsList,findDataInfo } from '../../api/documentManagement'
|
|
||||||
|
|
||||||
|
|
||||||
export default{
|
|
||||||
data(){
|
|
||||||
return{
|
|
||||||
params:{
|
|
||||||
lang:"",
|
|
||||||
type: 0, // 服务条款类型:数字1
|
|
||||||
},
|
|
||||||
infoParams:{
|
|
||||||
|
|
||||||
lang:this.$i18n?.locale || 'zh',
|
|
||||||
childType:"1", //1服务条款、2费率、3API文档
|
|
||||||
},
|
|
||||||
// 存储从后端获取的文档内容
|
|
||||||
info: "",
|
|
||||||
// 加载状态
|
|
||||||
loading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
|
|
||||||
// this.fetchDocumentsList(this.params)
|
|
||||||
this.fetchDocumentsInfo(this.infoParams)
|
|
||||||
},
|
|
||||||
methods:{
|
|
||||||
/**
|
|
||||||
* 获取文档列表
|
|
||||||
*/
|
|
||||||
// async fetchDocumentsList(){
|
|
||||||
// try {
|
|
||||||
// this.loading = true
|
|
||||||
// const res = await documentsList(this.params)
|
|
||||||
// console.log('文档列表:', res)
|
|
||||||
|
|
||||||
// if (res && res.code === 200 && res.rows && res.rows.length > 0) {
|
|
||||||
// console.log('请求参数:', res.rows)
|
|
||||||
// this.infoParams.id = res.rows[0].id
|
|
||||||
// this.infoParams.lang = this.$i18n?.locale || 'zh'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (this.infoParams.id && this.infoParams.lang) {
|
|
||||||
// await this.fetchDocumentsInfo()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// console.warn('未获取到文档列表数据')
|
|
||||||
// this.info = ""
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('获取文档列表失败:', error)
|
|
||||||
// this.info = ""
|
|
||||||
// } finally {
|
|
||||||
// this.loading = false
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取具体文档内容
|
|
||||||
*/
|
|
||||||
async fetchDocumentsInfo(params){
|
|
||||||
this.setLoading('loading', true);
|
|
||||||
try {
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
|
|
||||||
if (res && res.code === 200 ) {
|
|
||||||
// wangeditor 直接输出 HTML,直接使用
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
} else {
|
|
||||||
console.warn('获取文档内容失败:', res)
|
|
||||||
this.info = ""
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取文档内容失败:', error)
|
|
||||||
this.info = ""
|
|
||||||
}
|
|
||||||
this.setLoading('loading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ServiceTerms" v-loading="loading">
|
<div class="ServiceTerms">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 动态内容区域 - 从后端获取的文档内容 -->
|
|
||||||
<section class="content">
|
|
||||||
<div v-if="loading" class="loading-container">
|
|
||||||
<el-icon class="is-loading">
|
|
||||||
<i class="el-icon-loading"></i>
|
|
||||||
</el-icon>
|
|
||||||
<span class="loading-text">{{ $t(`ServiceTerms.loadingText`) || "正在加载文档内容..." }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else-if="info && info.trim()" class="dynamic-content" v-html="info"></div>
|
|
||||||
|
|
||||||
<!-- 如果没有动态内容,显示提示信息 -->
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t(`ServiceTerms.noContent`) || "暂无自定义文档内容" }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<section v-if="$isMobile">
|
<section v-if="$isMobile">
|
||||||
<h4 >{{ $t(`ServiceTerms.title`) }}</h4>
|
<h4 >{{ $t(`ServiceTerms.title`) }}</h4>
|
||||||
|
|
||||||
@@ -41,8 +18,7 @@
|
|||||||
<div class="textBox">
|
<div class="textBox">
|
||||||
<p>{{ $t(`ServiceTerms.clauseService1`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseService1`) }}</p>
|
||||||
<p>{{ $t(`ServiceTerms.clauseService2`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseService2`) }}</p>
|
||||||
|
<p><span style="font-weight: 600;">{{ $t(`ServiceTerms.clauseService3`) }} </span>{{ $t(`ServiceTerms.clauseService4`) }}</p>
|
||||||
<p style="text-align: justify;"><span style="font-weight: 600 ;text-align: justify;">{{ $t(`ServiceTerms.clauseService3`) }} </span>{{ $t(`ServiceTerms.clauseService4`) }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -112,7 +88,13 @@
|
|||||||
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="clauseBox">
|
||||||
|
<h5>{{ $t(`ServiceTerms.title11`) }}</h5>
|
||||||
|
<div class="textBox">
|
||||||
|
<p>{{ $t(`ServiceTerms.clauseLaw1`) }}</p>
|
||||||
|
<p>{{ $t(`ServiceTerms.clauseLaw2`) }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -135,8 +117,7 @@
|
|||||||
<div class="textBox">
|
<div class="textBox">
|
||||||
<p>{{ $t(`ServiceTerms.clauseService1`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseService1`) }}</p>
|
||||||
<p>{{ $t(`ServiceTerms.clauseService2`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseService2`) }}</p>
|
||||||
|
<p><span style="font-weight: 600;">{{ $t(`ServiceTerms.clauseService3`) }} </span>{{ $t(`ServiceTerms.clauseService4`) }}</p>
|
||||||
<p style="text-align: justify;"><span style="font-weight: 600;text-align: justify;">{{ $t(`ServiceTerms.clauseService3`) }} </span>{{ $t(`ServiceTerms.clauseService4`) }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -206,17 +187,21 @@
|
|||||||
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<section class="clauseBox">
|
||||||
|
<h3>{{ $t(`ServiceTerms.title11`) }}</h3>
|
||||||
|
<div class="textBox">
|
||||||
|
<p>{{ $t(`ServiceTerms.clauseLaw1`) }}</p>
|
||||||
|
<p>{{ $t(`ServiceTerms.clauseLaw2`) }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
</section> -->
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Index from './index'
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [Index],
|
|
||||||
metaInfo: {
|
metaInfo: {
|
||||||
meta: [
|
meta: [
|
||||||
{
|
{
|
||||||
@@ -263,144 +248,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-content :deep(p) {
|
|
||||||
max-width: 100% !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: break-word !important; /* 优先按单词/字符断行 */
|
|
||||||
overflow-wrap: anywhere !important; /* 极端长串也强制换行 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
.dynamic-content :deep(a) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
.dynamic-content :deep(li) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-content :deep(pre) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-content :deep(font) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
.dynamic-content :deep(h2) {
|
|
||||||
font-size: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-content :deep(h3) {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动端动态内容样式
|
|
||||||
.content {
|
|
||||||
margin-bottom: 20px !important;
|
|
||||||
|
|
||||||
// 移动端加载状态样式
|
|
||||||
.loading-container {
|
|
||||||
width: 100% !important;
|
|
||||||
margin: 20px auto !important;
|
|
||||||
padding: 20px 0 !important;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
font-size: 20px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移动端无内容样式
|
|
||||||
.no-content {
|
|
||||||
width: 100% !important;
|
|
||||||
margin: 20px auto !important;
|
|
||||||
padding: 20px 0 !important;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-content {
|
|
||||||
width: 100% !important;
|
|
||||||
padding: 10px !important;
|
|
||||||
/* 统一控制富文本行距与段落间距(移动端) */
|
|
||||||
--dc-line-height: 1.8; /* 行距:1.6~2 可按需调整 */
|
|
||||||
--dc-p-margin: 0.6em; /* 段落上下间距 */
|
|
||||||
|
|
||||||
// 确保HTML标签正确渲染
|
|
||||||
:deep(strong) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(em) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(code) {
|
|
||||||
background-color: #f5f5f5 !important;
|
|
||||||
padding: 2px 4px !important;
|
|
||||||
border-radius: 3px !important;
|
|
||||||
font-family: 'Courier New', monospace !important;
|
|
||||||
font-size: 0.9em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(del) {
|
|
||||||
text-decoration: line-through !important;
|
|
||||||
color: #666 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(a) {
|
|
||||||
color: #007bff !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(p) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: var(--dc-line-height) !important;
|
|
||||||
margin: var(--dc-p-margin) 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
:deep(div) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: var(--dc-line-height) !important;
|
|
||||||
margin: var(--dc-p-margin) 0 !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important;
|
|
||||||
word-wrap: break-word !important;
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,122 +281,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态内容样式
|
|
||||||
.content {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
|
|
||||||
// 加载状态样式
|
|
||||||
.loading-container {
|
|
||||||
width: 70%;
|
|
||||||
margin: 40px auto;
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
font-size: 24px;
|
|
||||||
color: #409eff;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 无内容样式
|
|
||||||
.no-content {
|
|
||||||
width: 70%;
|
|
||||||
margin: 40px auto;
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #999;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dynamic-content {
|
|
||||||
width: 70%;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 20px 0;
|
|
||||||
/* 统一控制富文本行距与段落间距(桌面端) */
|
|
||||||
--dc-line-height: 1.8; /* 行距:1.6~2 可按需调整 */
|
|
||||||
--dc-p-margin: 0.6em; /* 段落上下间距 */
|
|
||||||
|
|
||||||
// 确保HTML标签正确渲染
|
|
||||||
:deep(strong) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(em) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(code) {
|
|
||||||
background-color: #f5f5f5 !important;
|
|
||||||
padding: 2px 4px !important;
|
|
||||||
border-radius: 3px !important;
|
|
||||||
font-family: 'Courier New', monospace !important;
|
|
||||||
font-size: 0.9em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(del) {
|
|
||||||
text-decoration: line-through !important;
|
|
||||||
color: #666 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(a) {
|
|
||||||
color: #007bff !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(p) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: var(--dc-line-height) !important;
|
|
||||||
margin: var(--dc-p-margin) 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
:deep(div) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: var(--dc-line-height) !important;
|
|
||||||
margin: var(--dc-p-margin) 0 !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important;
|
|
||||||
word-wrap: break-word !important;
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -92,7 +92,7 @@ export default {
|
|||||||
this.params.maId = this.receiveData.id
|
this.params.maId = this.receiveData.id
|
||||||
}
|
}
|
||||||
this.fetchList(this.listParams)
|
this.fetchList(this.listParams)
|
||||||
this.registerRecoveryMethod('fetchList', this.listParams);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
@@ -100,8 +100,7 @@ export default {
|
|||||||
return getImageUrl(path);
|
return getImageUrl(path);
|
||||||
},
|
},
|
||||||
async fetchAddNoticeEmail(params){
|
async fetchAddNoticeEmail(params){
|
||||||
// this.addMinerLoading = true
|
this.addMinerLoading = true
|
||||||
this.setLoading('addMinerLoading', true);
|
|
||||||
const data = await getAddNoticeEmail(params)
|
const data = await getAddNoticeEmail(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -122,18 +121,17 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
async fetchList(params){
|
async fetchList(params){
|
||||||
// this.alertsLoading=true
|
this.alertsLoading=true
|
||||||
this.setLoading('alertsLoading', true);
|
|
||||||
const data = await getList(params)
|
const data = await getList(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.tableData = data.rows
|
this.tableData = data.rows
|
||||||
|
|
||||||
}
|
}
|
||||||
this.setLoading('alertsLoading', false);
|
this.alertsLoading=false
|
||||||
|
|
||||||
},
|
},
|
||||||
async fetchCode(params){
|
async fetchCode(params){
|
||||||
@@ -149,8 +147,7 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
async fetchUpdateInfo(params){
|
async fetchUpdateInfo(params){
|
||||||
// this.addMinerLoading = true
|
this.addMinerLoading = true
|
||||||
this.setLoading('addMinerLoading', true);
|
|
||||||
const data = await getUpdateInfo(params)
|
const data = await getUpdateInfo(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -162,12 +159,11 @@ export default {
|
|||||||
this.fetchList(this.listParams)
|
this.fetchList(this.listParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
async fetchDeleteEmail(params){
|
async fetchDeleteEmail(params){
|
||||||
// this.deleteLoading = true
|
this.deleteLoading = true
|
||||||
this.setLoading('deleteLoading', true);
|
|
||||||
const data = await deleteEmail(params)
|
const data = await deleteEmail(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -179,7 +175,7 @@ export default {
|
|||||||
this.fetchList(this.listParams)
|
this.fetchList(this.listParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('deleteLoading', false);
|
this.deleteLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -66,15 +66,15 @@ export default {
|
|||||||
estimatedTime:"course.estimatedTimeRxd",
|
estimatedTime:"course.estimatedTimeRxd",
|
||||||
describe:"course.describeRxd",
|
describe:"course.describeRxd",
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// value:"enx",
|
value:"enx",
|
||||||
// label:"Entropyx(enx)",
|
label:"Entropyx(enx)",
|
||||||
// img:`${this.$baseApi}img/enx.svg`,
|
img:`${this.$baseApi}img/enx.svg`,
|
||||||
// condition:"course.conditionEnx",
|
condition:"course.conditionEnx",
|
||||||
// interval:"course.intervalEnx",
|
interval:"course.intervalEnx",
|
||||||
// estimatedTime:"course.estimatedTimeEnx",
|
estimatedTime:"course.estimatedTimeEnx",
|
||||||
// describe:"course.describeEnx",
|
describe:"course.describeEnx",
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
value:"alph",
|
value:"alph",
|
||||||
label:"alephium",
|
label:"alephium",
|
||||||
@@ -85,25 +85,6 @@ export default {
|
|||||||
describe:"course.describeAlph",
|
describe:"course.describeAlph",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
value:"xmr",
|
|
||||||
label:"xmr",
|
|
||||||
img:`${this.$baseApi}img/xmr.png`,
|
|
||||||
condition:"course.conditionXmr",
|
|
||||||
interval:"course.intervalXmr",
|
|
||||||
estimatedTime:"course.estimatedTimeXmr",
|
|
||||||
describe:"course.describeXmr",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value:"sha3x",
|
|
||||||
label:"xtm(sha3x)",
|
|
||||||
img:`${this.$baseApi}img/xtm.svg`,
|
|
||||||
condition:"course.conditionXtm",
|
|
||||||
interval:"course.intervalXtm",
|
|
||||||
estimatedTime:"course.estimatedTimeXtm",
|
|
||||||
describe:"course.describeXtm",
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
import { documentsList,findDataInfo} from '../../api/documentManagement'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地存储选中的问题ID的键名
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
const SELECTED_PROBLEM_ID_KEY = 'announcementDetails:selectedId'
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
problems: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "如何开始挖矿?",
|
|
||||||
content: "详细步骤:注册、配置矿机、连接矿池。",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "如何查看收益?",
|
|
||||||
content: "登录后在个人中心查看收益统计。",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: "如何联系客服?",
|
|
||||||
content: "可通过在线客服或提交工单联系我们。",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
listParams:{
|
|
||||||
type:"3",//常见问题
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:50
|
|
||||||
},
|
|
||||||
problemLoading:false,
|
|
||||||
DetailsParams:{
|
|
||||||
id:"",
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
},
|
|
||||||
info:""
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
// this.DetailsParams.id = this.$route.query.id;
|
|
||||||
// console.log(this.$route.query.id,"this.DetailsParams.id");
|
|
||||||
// if (this.DetailsParams.id) {
|
|
||||||
// this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
// }
|
|
||||||
this.fetchProblemsList(this.listParams)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchProblemsList(params) {
|
|
||||||
this.setLoading('problemLoading', true);
|
|
||||||
const res = await documentsList(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
this.problems = res.rows;
|
|
||||||
// 优先级:URL 参数 > 本地存储 > 列表首项
|
|
||||||
const routeId = this.$route && this.$route.query && this.$route.query.id ? String(this.$route.query.id) : ''
|
|
||||||
const savedId = this.getSavedSelectedId()
|
|
||||||
|
|
||||||
let resolvedId = routeId || savedId || ''
|
|
||||||
|
|
||||||
if (!resolvedId && this.problems && this.problems.length > 0) {
|
|
||||||
resolvedId = String(this.problems[0].id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果存在但不在当前列表中,则回退到首项
|
|
||||||
if (resolvedId) {
|
|
||||||
const existsInList = (this.problems || []).some(item => String(item.id) === String(resolvedId))
|
|
||||||
if (!existsInList && this.problems && this.problems.length > 0) {
|
|
||||||
resolvedId = String(this.problems[0].id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.DetailsParams.id = resolvedId
|
|
||||||
|
|
||||||
// 同步到URL与本地存储
|
|
||||||
this.persistSelectedId(this.DetailsParams.id)
|
|
||||||
this.updateRouteQueryId(this.DetailsParams.id)
|
|
||||||
|
|
||||||
if (this.DetailsParams.id) {
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setLoading('problemLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchProblemDetails(params) {
|
|
||||||
this.setLoading('problemLoading', true);
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
console.log(res,"res");
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
}
|
|
||||||
this.setLoading('problemLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转到问题详情页
|
|
||||||
* @param {number} id 问题ID
|
|
||||||
*/
|
|
||||||
handleClick(id) {
|
|
||||||
// 更新当前选中ID
|
|
||||||
this.DetailsParams.id = id
|
|
||||||
// 持久化并同步URL
|
|
||||||
this.persistSelectedId(this.DetailsParams.id)
|
|
||||||
this.updateRouteQueryId(this.DetailsParams.id)
|
|
||||||
// 获取详情
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将选中的问题ID持久化到本地存储
|
|
||||||
* @param {string|number} id 问题ID
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
persistSelectedId(id) {
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem(SELECTED_PROBLEM_ID_KEY, String(id))
|
|
||||||
} catch (error) {
|
|
||||||
// 上报或静默处理本地存储异常
|
|
||||||
console.error('persistSelectedId error', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取本地存储中保存的选中问题ID
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getSavedSelectedId() {
|
|
||||||
try {
|
|
||||||
return window.localStorage.getItem(SELECTED_PROBLEM_ID_KEY) || ''
|
|
||||||
} catch (error) {
|
|
||||||
console.error('getSavedSelectedId error', error)
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 replace 同步更新当前路由的查询参数中的 id
|
|
||||||
* 避免产生新的历史记录条目
|
|
||||||
* @param {string|number} id 问题ID
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
updateRouteQueryId(id) {
|
|
||||||
try {
|
|
||||||
if (!this.$route) return
|
|
||||||
const targetId = String(id)
|
|
||||||
const currentId = this.$route && this.$route.query && this.$route.query.id ? String(this.$route.query.id) : ''
|
|
||||||
if (currentId === targetId) return
|
|
||||||
|
|
||||||
const nextQuery = { ...(this.$route.query || {}), id: targetId }
|
|
||||||
if (this.$router && typeof this.$router.replace === 'function') {
|
|
||||||
const maybePromise = this.$router.replace({ query: nextQuery })
|
|
||||||
if (maybePromise && typeof maybePromise.catch === 'function') {
|
|
||||||
maybePromise.catch(() => {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('updateRouteQueryId error', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="announcementDetails">
|
|
||||||
<section class="container">
|
|
||||||
<section class="leftNav">
|
|
||||||
<div
|
|
||||||
class="leftNav-item "
|
|
||||||
:class="{active:DetailsParams.id == item.id}"
|
|
||||||
v-for="item in problems"
|
|
||||||
:key="item.id"
|
|
||||||
@click="handleClick(item.id)"
|
|
||||||
@keydown.enter.space="handleClick(item.id)"
|
|
||||||
tabindex="0"
|
|
||||||
role="button"
|
|
||||||
:aria-label="item.title"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="rightContent">
|
|
||||||
<div v-if="problemLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{ $t('home.loadingContent') || '正在加载内容...' }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="info && info.trim()" class="dynamic-content" v-html="info"></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t('home.noContent') || '暂无内容' }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import IndexJs from "./index.js";
|
|
||||||
export default {
|
|
||||||
mixins: [IndexJs],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.announcementDetails{
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background: #F8F9FA;
|
|
||||||
padding-top: 60px;
|
|
||||||
}
|
|
||||||
.container{
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
width: 70vw;
|
|
||||||
height: 80vh;
|
|
||||||
margin: 0 auto;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
padding: 20px;
|
|
||||||
|
|
||||||
padding-top: 50px;
|
|
||||||
.leftNav{
|
|
||||||
width: 260px;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 8px; // 预留滚动条空间,避免抖动
|
|
||||||
border-right: 1px solid #f1f2f3;
|
|
||||||
}
|
|
||||||
.rightContent{
|
|
||||||
flex: 1;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 32px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 20px;
|
|
||||||
.dynamic-content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
// 富文本样式
|
|
||||||
:deep(table) {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
:deep(p) {
|
|
||||||
line-height: 35px;
|
|
||||||
margin: 8px 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
:deep(th), :deep(td) {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
:deep(th) {
|
|
||||||
background: #f3f4f6;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
:deep(strong), :deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
:deep(em), :deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
:deep(a) {
|
|
||||||
color: #007bff !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.loading-container {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
.loading-text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.no-content {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #999;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.leftNav-item{
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
padding: 10px 14px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.5;
|
|
||||||
border-radius: 8px;
|
|
||||||
position: relative;
|
|
||||||
outline: none;
|
|
||||||
transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
|
|
||||||
|
|
||||||
&:hover{
|
|
||||||
background: #f7f7fb;
|
|
||||||
color: #4c36ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus-visible{
|
|
||||||
box-shadow: 0 0 0 3px rgba(101,31,255,0.2);
|
|
||||||
background: #f7f7fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active{
|
|
||||||
color: #4c36ff;
|
|
||||||
background: #f3f2ff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active::before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: -8px;
|
|
||||||
top: 8px;
|
|
||||||
bottom: 8px;
|
|
||||||
width: 3px;
|
|
||||||
background: #4c36ff;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 自定义滚动条,提升观感 */
|
|
||||||
.leftNav::-webkit-scrollbar{
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
.leftNav::-webkit-scrollbar-thumb{
|
|
||||||
background: #e2e2e8;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
.leftNav:hover::-webkit-scrollbar-thumb{
|
|
||||||
background: #cfcfe7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
import { documentsList } from '../../api/documentManagement'
|
|
||||||
export default {
|
|
||||||
name: 'Announcements',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
// 加载状态
|
|
||||||
loading: false,
|
|
||||||
|
|
||||||
// 搜索关键词
|
|
||||||
searchKeyword: '',
|
|
||||||
|
|
||||||
// 分页参数
|
|
||||||
currentPage: 1,
|
|
||||||
totalCount: 0,
|
|
||||||
|
|
||||||
// 公告数据
|
|
||||||
announcements: [
|
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// title: 'ZEN挖矿服务即将结束',
|
|
||||||
// summary: 'ZEN挖矿服务将于近期结束,请及时调整您的挖矿设置。',
|
|
||||||
// type: '重要通知',
|
|
||||||
// createTime: '2025-01-20T10:00:00.000Z',
|
|
||||||
// isTop: true
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 2,
|
|
||||||
// title: 'LKY即将减半',
|
|
||||||
// summary: 'LKY币种将在近期进行减半操作,请关注相关通知。',
|
|
||||||
// type: '系统公告',
|
|
||||||
// createTime: '2025-01-19T15:30:00.000Z',
|
|
||||||
// isTop: false
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 3,
|
|
||||||
// title: 'PEP即将减产',
|
|
||||||
// summary: 'PEP币种挖矿难度调整,产量将有所减少。',
|
|
||||||
// type: '市场动态',
|
|
||||||
// createTime: '2025-01-18T09:15:00.000Z',
|
|
||||||
// isTop: false
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 4,
|
|
||||||
// title: 'ETC+ZIL挖矿服务已结束',
|
|
||||||
// summary: 'ETC+ZIL双挖服务已正式结束,感谢您的支持。',
|
|
||||||
// type: '服务通知',
|
|
||||||
// createTime: '2025-01-17T14:45:00.000Z',
|
|
||||||
// isTop: false
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 5,
|
|
||||||
// title: '有关2025年06月19日SCT池异常的说明',
|
|
||||||
// summary: 'SCT矿池在指定时间出现异常情况,现已修复并提供补偿方案。',
|
|
||||||
// type: '故障说明',
|
|
||||||
// createTime: '2025-01-16T11:20:00.000Z',
|
|
||||||
// isTop: false
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 6,
|
|
||||||
// title: 'FB单挖矿池下线公告',
|
|
||||||
// summary: 'FB单挖矿池将于本月底正式下线,请及时转移算力。',
|
|
||||||
// type: '下线通知',
|
|
||||||
// createTime: '2025-01-15T16:10:00.000Z',
|
|
||||||
// isTop: false
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
|
|
||||||
// 搜索防抖定时器
|
|
||||||
searchTimer: null,
|
|
||||||
|
|
||||||
// Markdown 使用规则指南
|
|
||||||
showMarkdownGuide: false,
|
|
||||||
viewMode: 'list', // 'list' or 'editor'0
|
|
||||||
listParams:{
|
|
||||||
type:"3",
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:10
|
|
||||||
},
|
|
||||||
announcementsLoading:false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
try {
|
|
||||||
this.TypeList = JSON.parse(localStorage.getItem('TypeList'))
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
// this.loadAnnouncements();
|
|
||||||
|
|
||||||
this.fetchAllList(this.listParams)
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
async fetchAllList(params){
|
|
||||||
this.setLoading('announcementsLoading', true);
|
|
||||||
const res = await documentsList(params)
|
|
||||||
console.log(res,"res");
|
|
||||||
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.announcements = res.rows
|
|
||||||
this.totalCount = res.total
|
|
||||||
}
|
|
||||||
this.setLoading('announcementsLoading', false);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 加载公告数据
|
|
||||||
*/
|
|
||||||
async loadAnnouncements() {
|
|
||||||
this.loading = true;
|
|
||||||
try {
|
|
||||||
// 这里应该调用API获取公告数据
|
|
||||||
// const response = await this.$api.getAnnouncements({
|
|
||||||
// page: this.currentPage,
|
|
||||||
// pageSize: this.pageSize,
|
|
||||||
// keyword: this.searchKeyword
|
|
||||||
// });
|
|
||||||
// this.announcements = response.data;
|
|
||||||
// this.totalCount = response.total;
|
|
||||||
|
|
||||||
// 模拟API调用延迟
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('加载公告失败:', error);
|
|
||||||
this.$message.error(this.$t('announcements.loadError') || '加载公告失败');
|
|
||||||
} finally {
|
|
||||||
this.loading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理搜索输入
|
|
||||||
*/
|
|
||||||
handleSearchInput() {
|
|
||||||
if (this.searchTimer) {
|
|
||||||
clearTimeout(this.searchTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 防抖处理,500ms后执行搜索
|
|
||||||
this.searchTimer = setTimeout(() => {
|
|
||||||
this.handleSearch();
|
|
||||||
}, 500);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行搜索
|
|
||||||
*/
|
|
||||||
handleSearch() {
|
|
||||||
this.currentPage = 1;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理页码变化
|
|
||||||
*/
|
|
||||||
handleCurrentChange(page) {
|
|
||||||
this.currentPage = page;
|
|
||||||
this.listParams.pageNum = page
|
|
||||||
this.fetchAllList(this.listParams)
|
|
||||||
},
|
|
||||||
handleSizeChange(size){
|
|
||||||
this.listParams.pageNum = 1
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.listParams.pageSize = size
|
|
||||||
this.fetchAllList(this.listParams)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理公告点击
|
|
||||||
*/
|
|
||||||
handleAnnouncementClick(announcement) {
|
|
||||||
|
|
||||||
console.log(announcement,"announcement");
|
|
||||||
let url = `/${this.$i18n.locale}/announcementDetails`
|
|
||||||
// 跳转到公告详情页
|
|
||||||
this.$router.push({
|
|
||||||
path:url,
|
|
||||||
query:{
|
|
||||||
id:announcement.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看所有公告
|
|
||||||
*/
|
|
||||||
handleViewAll() {
|
|
||||||
// 可以跳转到完整的公告列表页面或展开显示更多
|
|
||||||
this.pageSize = 20;
|
|
||||||
this.loadAnnouncements();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换Markdown使用规则指南的显示状态
|
|
||||||
*/
|
|
||||||
toggleMarkdownGuide() {
|
|
||||||
this.showMarkdownGuide = !this.showMarkdownGuide;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换视图模式 (list/editor)
|
|
||||||
*/
|
|
||||||
switchMode(mode) {
|
|
||||||
this.viewMode = mode;
|
|
||||||
// Markdown指南现在完全独立控制,不与视图模式绑定
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回首页
|
|
||||||
*/
|
|
||||||
goHome() {
|
|
||||||
this.$router.push('/');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化日期
|
|
||||||
*/
|
|
||||||
formatDate(dateString) {
|
|
||||||
try {
|
|
||||||
return `${dateString.split("T")[0]} ${dateString.split("T")[1]}`
|
|
||||||
} catch (error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelType(type){
|
|
||||||
try {
|
|
||||||
let label = this.TypeList.find(item => item.value == type).label
|
|
||||||
return this.$t(label)
|
|
||||||
} catch (error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
// 清理定时器
|
|
||||||
if (this.searchTimer) {
|
|
||||||
clearTimeout(this.searchTimer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,192 +0,0 @@
|
|||||||
import { documentsList, findDataInfo } from '../../api/documentManagement'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ApiFile',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
listParams: {
|
|
||||||
lang: `${this.$i18n.locale}`,
|
|
||||||
childType: 3,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:50
|
|
||||||
},
|
|
||||||
DetailsParams: {
|
|
||||||
lang: `${this.$i18n.locale}`,
|
|
||||||
childType:3,//1服务条款、2费率、3API文档 childType
|
|
||||||
},
|
|
||||||
navContent: {},
|
|
||||||
documentLoading: true,
|
|
||||||
documentContent: '',
|
|
||||||
documentError: '',
|
|
||||||
navList:[],
|
|
||||||
info: '',
|
|
||||||
contentShow:false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getDocumentsList(this.listParams)
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async getDocumentsList(params) {
|
|
||||||
try {
|
|
||||||
const res = await documentsList(params)
|
|
||||||
this.setLoading('documentLoading', true);
|
|
||||||
if (res && res.code === 200) {
|
|
||||||
this.navList = res.rows
|
|
||||||
|
|
||||||
if (this.$route.query.id) {
|
|
||||||
this.DetailsParams.id = this.$route.query.id
|
|
||||||
|
|
||||||
}else{
|
|
||||||
this.DetailsParams.id = res.rows[0].id;
|
|
||||||
}
|
|
||||||
if (this.DetailsParams.id) {
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取文档列表失败:', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchProblemDetails(params) {
|
|
||||||
this.setLoading('documentLoading', true);
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
this.contentShow = true
|
|
||||||
}
|
|
||||||
this.setLoading('documentLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
backMenu(){
|
|
||||||
this.contentShow = false
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// async getDocumentsInfo(params) {
|
|
||||||
// this.documentLoading = true
|
|
||||||
// this.documentError = ''
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const res = await findDataInfo(params)
|
|
||||||
// console.log('文档详情:', res)
|
|
||||||
|
|
||||||
// if (res && res.code === 200 && res.data) {
|
|
||||||
// this.navContent = res.data
|
|
||||||
// // 将Markdown内容转换为HTML
|
|
||||||
// this.documentContent = this.markdownToHtml(res.data.content || '')
|
|
||||||
// } else {
|
|
||||||
// this.documentError = '获取文档失败: ' + (res?.msg || '未知错误')
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('获取文档详情失败:', error)
|
|
||||||
// this.documentError = '获取文档失败: ' + (error.message || '网络错误')
|
|
||||||
// } finally {
|
|
||||||
// this.documentLoading = false
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 改进的Markdown转HTML方法
|
|
||||||
* @param {string} markdown - Markdown内容
|
|
||||||
* @returns {string} - HTML内容
|
|
||||||
*/
|
|
||||||
markdownToHtml(markdown) {
|
|
||||||
if (!markdown) return ''
|
|
||||||
|
|
||||||
// 先处理表格(在换行处理之前)
|
|
||||||
let html = this.processMarkdownTables(markdown)
|
|
||||||
|
|
||||||
html = html
|
|
||||||
// 标题处理
|
|
||||||
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
|
|
||||||
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
|
|
||||||
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
|
|
||||||
// 粗体和斜体
|
|
||||||
.replace(/\*\*(.*?)\*\*/gim, '<strong>$1</strong>')
|
|
||||||
.replace(/\*(.*?)\*/gim, '<em>$1</em>')
|
|
||||||
// 代码块
|
|
||||||
.replace(/```([\s\S]*?)```/gim, '<pre><code>$1</code></pre>')
|
|
||||||
.replace(/`([^`]*)`/gim, '<code>$1</code>')
|
|
||||||
// 链接
|
|
||||||
.replace(/\[([^\]]*)\]\(([^)]*)\)/gim, '<a href="$2" target="_blank">$1</a>')
|
|
||||||
|
|
||||||
// 处理段落和换行(避免影响表格)
|
|
||||||
const parts = html.split(/(<table[\s\S]*?<\/table>)/g)
|
|
||||||
html = parts.map(part => {
|
|
||||||
if (part.startsWith('<table')) {
|
|
||||||
return part // 保持表格不变
|
|
||||||
}
|
|
||||||
return part
|
|
||||||
.replace(/\n\n/gim, '</p><p>')
|
|
||||||
.replace(/\n/gim, '<br>')
|
|
||||||
}).join('')
|
|
||||||
|
|
||||||
// 包装段落
|
|
||||||
if (html && !html.startsWith('<') && !html.includes('<table')) {
|
|
||||||
html = '<p>' + html + '</p>'
|
|
||||||
}
|
|
||||||
|
|
||||||
return html
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理Markdown表格
|
|
||||||
* @param {string} text - 包含表格的文本
|
|
||||||
* @returns {string} - 转换后的HTML
|
|
||||||
*/
|
|
||||||
processMarkdownTables(text) {
|
|
||||||
// 匹配Markdown表格的正则表达式
|
|
||||||
const tableRegex = /(\|.*\|[\r\n]+)+/g
|
|
||||||
|
|
||||||
return text.replace(tableRegex, (match) => {
|
|
||||||
const lines = match.trim().split(/[\r\n]+/)
|
|
||||||
if (lines.length < 2) return match
|
|
||||||
|
|
||||||
let html = '<table border="1" style="border-collapse: collapse; width: 100%; margin: 15px 0;">\n'
|
|
||||||
|
|
||||||
lines.forEach((line, index) => {
|
|
||||||
line = line.trim()
|
|
||||||
if (!line.startsWith('|') || !line.endsWith('|')) return
|
|
||||||
|
|
||||||
// 移除首尾的 |
|
|
||||||
const content = line.slice(1, -1)
|
|
||||||
const cells = content.split('|').map(cell => cell.trim())
|
|
||||||
|
|
||||||
// 跳过分隔线(包含 --- 的行)
|
|
||||||
if (cells.some(cell => /^-+$/.test(cell))) return
|
|
||||||
|
|
||||||
const isHeader = index === 0
|
|
||||||
const tag = isHeader ? 'th' : 'td'
|
|
||||||
const style = isHeader ?
|
|
||||||
' style="background: #f8f9fa; font-weight: 600; padding: 8px 12px; border: 1px solid #ddd; text-align: left;"' :
|
|
||||||
' style="padding: 8px 12px; border: 1px solid #ddd; text-align: left;"'
|
|
||||||
|
|
||||||
html += ' <tr>\n'
|
|
||||||
cells.forEach(cell => {
|
|
||||||
html += ` <${tag}${style}>${cell}</${tag}>\n`
|
|
||||||
})
|
|
||||||
html += ' </tr>\n'
|
|
||||||
})
|
|
||||||
|
|
||||||
html += '</table>\n'
|
|
||||||
return html
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
clickJump(item) {
|
|
||||||
|
|
||||||
this.DetailsParams.id = item.id
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,420 +0,0 @@
|
|||||||
import { listBroadcast, getAddBroadcast, updateBroadcast, DeleteBroadcast, getBroadcast, dataInfo } from '../../api/broadcast'
|
|
||||||
import { isValidPath, getPathSuggestions } from '../../utils/routeUtils'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableData: [
|
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// createTime: "2025-06-24 10:00:00",
|
|
||||||
// content: "内isjisjfidjfjfjffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff容",
|
|
||||||
// createUser: "创建人",
|
|
||||||
// updateTime: "2025-06-24 10:00:00",
|
|
||||||
// updateUser: "修改人",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 2,
|
|
||||||
// createTime: "2025-06-24 10:00:00",
|
|
||||||
// content: "内容",
|
|
||||||
// createUser: "创建人",
|
|
||||||
// updateTime: "2025-06-24 10:00:00",
|
|
||||||
// updateUser: "修改人",
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
listParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 50
|
|
||||||
},
|
|
||||||
addParams: {
|
|
||||||
content: "",
|
|
||||||
buttonContent: "",
|
|
||||||
buttonPath: "",
|
|
||||||
},
|
|
||||||
editParams: {
|
|
||||||
content: "",
|
|
||||||
id: "",
|
|
||||||
buttonContent: "",
|
|
||||||
buttonPath: "",
|
|
||||||
},
|
|
||||||
dialogVisible: false,
|
|
||||||
bthLoading: false,
|
|
||||||
broadcastLoading: false,
|
|
||||||
editDialogVisible: false,
|
|
||||||
editLoading: false,
|
|
||||||
byteCount: "",
|
|
||||||
isOverLimit: false,
|
|
||||||
total: 0,
|
|
||||||
pageSizes: [50, 100, 300],
|
|
||||||
currentPage: 1,
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
|
|
||||||
|
|
||||||
let token
|
|
||||||
try {
|
|
||||||
token = JSON.parse(localStorage.getItem('token'))
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
if (token) {
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchList(params) {
|
|
||||||
|
|
||||||
this.setLoading('broadcastLoading', true);
|
|
||||||
const res = await listBroadcast(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.tableData = res.rows
|
|
||||||
this.total = res.total
|
|
||||||
}
|
|
||||||
this.setLoading('broadcastLoading', false);
|
|
||||||
},
|
|
||||||
async addBroadcast(params) {
|
|
||||||
this.setLoading('bthLoading', true);
|
|
||||||
|
|
||||||
// 发送请求前打印参数,用于调试
|
|
||||||
console.log('发送广播请求的参数:', params);
|
|
||||||
|
|
||||||
const res = await getAddBroadcast(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$message.success(this.$t("backendSystem.addSuccess"))
|
|
||||||
this.dialogVisible = false;
|
|
||||||
// 清空表单参数
|
|
||||||
this.addParams.content = ""
|
|
||||||
this.addParams.buttonContent = ""
|
|
||||||
this.addParams.buttonPath = ""
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
}
|
|
||||||
this.setLoading('bthLoading', false);
|
|
||||||
},
|
|
||||||
async getBroadcast(params) {
|
|
||||||
this.setLoading('editLoading', true);
|
|
||||||
const res = await dataInfo(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.editParams = {
|
|
||||||
...res.data,
|
|
||||||
// 确保按钮路径是字符串格式(如果是数组则转换为逗号分隔的字符串)
|
|
||||||
buttonPath: Array.isArray(res.data.buttonPath)
|
|
||||||
? res.data.buttonPath.join(',')
|
|
||||||
: (res.data.buttonPath || '')
|
|
||||||
};
|
|
||||||
this.editDialogVisible = true;
|
|
||||||
}
|
|
||||||
this.setLoading('editLoading', false);
|
|
||||||
},
|
|
||||||
async editBroadcast(params) {
|
|
||||||
this.setLoading('editLoading', true);
|
|
||||||
|
|
||||||
// 发送请求前打印参数,用于调试
|
|
||||||
console.log('发送编辑广播请求的参数:', params);
|
|
||||||
|
|
||||||
const res = await updateBroadcast(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$message.success(this.$t("backendSystem.editSuccess"))
|
|
||||||
this.editDialogVisible = false;
|
|
||||||
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
}
|
|
||||||
this.setLoading('editLoading', false);
|
|
||||||
},
|
|
||||||
async deleteBroadcast(params) {
|
|
||||||
const res = await DeleteBroadcast(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$message.success(this.$t("backendSystem.deleteSuccess"))
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelAddBroadcast() {
|
|
||||||
this.dialogVisible = true;
|
|
||||||
},
|
|
||||||
handleClose() {
|
|
||||||
this.dialogVisible = false;
|
|
||||||
this.addParams.content = ""
|
|
||||||
this.addParams.buttonContent = ""
|
|
||||||
this.addParams.buttonPath = ""
|
|
||||||
this.setLoading('bthLoading', false);
|
|
||||||
},
|
|
||||||
sureAddBroadcast() {
|
|
||||||
|
|
||||||
this.addParams.content = this.addParams.content.trim()
|
|
||||||
this.addParams.content = this.addParams.content.replace(/[\r\n]/g, '');
|
|
||||||
this.addParams.buttonPath = this.addParams.buttonPath.trim()
|
|
||||||
this.addParams.buttonPath = this.addParams.buttonPath.replace(/[\r\n]/g, '');
|
|
||||||
if (!this.addParams.content) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.addParams.buttonContent && this.addParams.buttonPath) || (!this.addParams.buttonContent && !this.addParams.buttonPath)) {
|
|
||||||
|
|
||||||
if (this.addParams.buttonPath) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
let pathArray = this.addParams.buttonPath.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证每个路径是否以/开头
|
|
||||||
const invalidPaths = pathArray.filter(path => !path.startsWith('/'));
|
|
||||||
if (invalidPaths.length > 0) {
|
|
||||||
this.$message.error(`路径必须以 / 开头: ${invalidPaths.join(', ')}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.addParams.buttonContent) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
let pathArray2 = this.addParams.buttonContent.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray2.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray2.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (this.addParams.buttonContent && this.addParams.buttonPath) {
|
|
||||||
if (pathArray.length !== pathArray2.length) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证通过,保持字符串格式传给后端(不转换为数组)
|
|
||||||
// this.addParams.buttonPath 保持原始字符串格式
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.addBroadcast(this.addParams);
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
sureEditBroadcast() {
|
|
||||||
this.editParams.content = this.editParams.content.trim()
|
|
||||||
this.editParams.content = this.editParams.content.replace(/[\r\n]/g, '');
|
|
||||||
let buttonContentArray
|
|
||||||
let pathArray
|
|
||||||
if (!this.editParams.content) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.editParams.buttonContent) {
|
|
||||||
this.editParams.buttonContent = this.editParams.buttonContent.trim().replace(/[\r\n]/g, '');
|
|
||||||
|
|
||||||
// 验证按钮内容和路径是否匹配
|
|
||||||
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
|
|
||||||
if (this.editParams.buttonContent) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
buttonContentArray = this.editParams.buttonContent.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (buttonContentArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (buttonContentArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有按钮路径,进行验证
|
|
||||||
if (this.editParams.buttonPath) {
|
|
||||||
this.editParams.buttonPath = this.editParams.buttonPath.trim().replace(/[\r\n]/g, '');
|
|
||||||
|
|
||||||
// 验证按钮内容和路径是否匹配
|
|
||||||
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
|
|
||||||
if (this.editParams.buttonPath) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
pathArray = this.editParams.buttonPath.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证每个路径是否以/开头
|
|
||||||
const invalidPaths = pathArray.filter(path => !path.startsWith('/'));
|
|
||||||
if (invalidPaths.length > 0) {
|
|
||||||
this.$message.error(`路径必须以 / 开头: ${invalidPaths.join(', ')}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.editParams.buttonContent && this.editParams.buttonPath) {
|
|
||||||
if (buttonContentArray.length !== pathArray.length) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.editBroadcast(this.editParams);
|
|
||||||
},
|
|
||||||
handleEdit(row) {
|
|
||||||
|
|
||||||
this.getBroadcast({ id: row.id });
|
|
||||||
},
|
|
||||||
handleEditClose() {
|
|
||||||
this.editDialogVisible = false;
|
|
||||||
this.editParams.content = ""
|
|
||||||
this.editParams.buttonContent = ""
|
|
||||||
this.editParams.buttonPath = ""
|
|
||||||
this.setLoading('editLoading', false);
|
|
||||||
},
|
|
||||||
handelDelete(row) {
|
|
||||||
this.deleteBroadcast({ id: row.id });
|
|
||||||
},
|
|
||||||
getUtf8Bytes(str) {
|
|
||||||
let bytes = 0;
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
|
||||||
const code = str.charCodeAt(i);
|
|
||||||
if (code <= 0x7f) bytes += 1;
|
|
||||||
else if (code <= 0x7ff) bytes += 2;
|
|
||||||
else if (code <= 0xffff) bytes += 3;
|
|
||||||
else bytes += 4;
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleInput(val, type = 'add') {
|
|
||||||
let bytes = this.getUtf8Bytes(val);
|
|
||||||
if (bytes > 100) {
|
|
||||||
this.isOverLimit = true;
|
|
||||||
// 截断到100字节
|
|
||||||
let newVal = '';
|
|
||||||
let total = 0;
|
|
||||||
for (let ch of val) {
|
|
||||||
let chBytes = this.getUtf8Bytes(ch);
|
|
||||||
if (total + chBytes > 100) break;
|
|
||||||
newVal += ch;
|
|
||||||
total += chBytes;
|
|
||||||
}
|
|
||||||
if (type === 'add') {
|
|
||||||
this.addParams.content = newVal;
|
|
||||||
} else {
|
|
||||||
this.editParams.content = newVal;
|
|
||||||
}
|
|
||||||
bytes = total;
|
|
||||||
} else {
|
|
||||||
this.isOverLimit = false;
|
|
||||||
if (type === 'add') {
|
|
||||||
this.addParams.content = val;
|
|
||||||
} else {
|
|
||||||
this.editParams.content = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.byteCount = bytes;
|
|
||||||
},
|
|
||||||
|
|
||||||
handelTime(time) {
|
|
||||||
return `${time.split("T")[0]} ${time.split("T")[1]}`
|
|
||||||
},
|
|
||||||
handleSizeChange(val) {
|
|
||||||
console.log(`每页 ${val} 条`);
|
|
||||||
this.listParams.pageSize = val
|
|
||||||
this.listParams.pageNum = 1
|
|
||||||
this.currentPage = 1
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
|
|
||||||
},
|
|
||||||
handleCurrentChange(val) {
|
|
||||||
console.log(`当前页: ${val}`);
|
|
||||||
this.listParams.pageNum = val
|
|
||||||
this.fetchList(this.listParams);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取有效路径建议信息
|
|
||||||
* @returns {Array} 路径建议列表
|
|
||||||
*/
|
|
||||||
getValidPathSuggestions() {
|
|
||||||
// 移除路径建议,返回空数组
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示路径使用帮助
|
|
||||||
*/
|
|
||||||
showPathHelp() {
|
|
||||||
const helpMessage = `
|
|
||||||
路径规则:
|
|
||||||
• 多个路径用逗号分隔
|
|
||||||
• 路径格式自由,不做严格验证
|
|
||||||
• 支持任意路径格式
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.$alert(helpMessage, '路径格式说明', {
|
|
||||||
confirmButtonText: '知道了',
|
|
||||||
type: 'info',
|
|
||||||
customClass: 'path-help-dialog'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化按钮内容显示
|
|
||||||
* @param {string} buttonContent - 逗号分隔的按钮内容字符串
|
|
||||||
* @returns {Array} 按钮内容数组
|
|
||||||
*/
|
|
||||||
formatButtonContent(buttonContent) {
|
|
||||||
if (!buttonContent || typeof buttonContent !== 'string') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return buttonContent
|
|
||||||
.split(/[,,]/)
|
|
||||||
.map(btn => btn.trim())
|
|
||||||
.filter(btn => btn);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化按钮路径显示
|
|
||||||
* @param {string} buttonPath - 逗号分隔的路径字符串
|
|
||||||
* @returns {Array} 路径数组
|
|
||||||
*/
|
|
||||||
formatButtonPath(buttonPath) {
|
|
||||||
if (!buttonPath || typeof buttonPath !== 'string') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return buttonPath
|
|
||||||
.split(/[,,]/)
|
|
||||||
.map(path => path.trim())
|
|
||||||
.filter(path => path);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,382 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-loading="broadcastLoading">
|
|
||||||
<div class="main-title-box">
|
|
||||||
<div class="main-title">{{ $t("backendSystem.publishedBroadcast") }}</div>
|
|
||||||
<el-button class="add-btn" @click="handelAddBroadcast"
|
|
||||||
>{{ $t("backendSystem.addBroadcast") }}
|
|
||||||
<i class="iconfont icon-youjiantou1 arrow"></i
|
|
||||||
></el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-table
|
|
||||||
:data="tableData"
|
|
||||||
border
|
|
||||||
style="width: 100%; margin-bottom: 18px"
|
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
|
||||||
height="60vh"
|
|
||||||
>
|
|
||||||
<el-table-column prop="id" label="ID" width="60" show-overflow-tooltip />
|
|
||||||
<el-table-column
|
|
||||||
prop="createTime"
|
|
||||||
:label="$t('backendSystem.createTime')"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.createTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="content"
|
|
||||||
:label="$t('backendSystem.content')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="createUser"
|
|
||||||
:label="$t('backendSystem.createUser')"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
prop="buttonContent"
|
|
||||||
:label="$t('backendSystem.bthContent2')"
|
|
||||||
width="200"
|
|
||||||
show-overflow-tooltip
|
|
||||||
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<div v-if="scope.row.buttonContent">
|
|
||||||
<el-tag
|
|
||||||
v-for="(button, index) in formatButtonContent(scope.row.buttonContent)"
|
|
||||||
:key="index"
|
|
||||||
size="small"
|
|
||||||
style="margin: 2px;"
|
|
||||||
>
|
|
||||||
{{ button }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
<span v-else style="color: #999;">无</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="buttonPath"
|
|
||||||
:label="$t('backendSystem.bthPath2')"
|
|
||||||
width="250"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<div v-if="scope.row.buttonPath">
|
|
||||||
<div
|
|
||||||
v-for="(path, index) in formatButtonPath(scope.row.buttonPath)"
|
|
||||||
:key="index"
|
|
||||||
class="path-item"
|
|
||||||
style="font-size: 12px;"
|
|
||||||
>
|
|
||||||
{{ index + 1 }}. {{ path }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span v-else style="color: #999;">无</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="updateTime"
|
|
||||||
:label="$t('backendSystem.updateTime')"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.updateTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="updateUser"
|
|
||||||
:label="$t('backendSystem.updateUser')"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column :label="$t('backendSystem.operation')" width="160">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" @click="handleEdit(scope.row)">{{
|
|
||||||
$t("backendSystem.edit")
|
|
||||||
}}</el-button>
|
|
||||||
|
|
||||||
<el-popconfirm
|
|
||||||
:confirm-button-text="$t(`work.confirm`)"
|
|
||||||
:cancel-button-text="$t(`work.cancel`)"
|
|
||||||
icon="el-icon-info"
|
|
||||||
icon-color="red"
|
|
||||||
:title="$t(`alerts.deleteRemind`)"
|
|
||||||
@confirm="handelDelete(scope.row)"
|
|
||||||
>
|
|
||||||
<el-button class="elBtn" size="mini" slot="reference">{{
|
|
||||||
$t(`personal.delete`)
|
|
||||||
}}</el-button>
|
|
||||||
</el-popconfirm>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24" style="display: flex; justify-content: center">
|
|
||||||
<el-pagination
|
|
||||||
style="margin: 0 auto; margin-top: 10px"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page.sync="currentPage"
|
|
||||||
:page-sizes="pageSizes"
|
|
||||||
:page-size="listParams.pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total"
|
|
||||||
>
|
|
||||||
</el-pagination>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<!-- 新增广播弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
:title="$t('backendSystem.dialogTitle')"
|
|
||||||
:visible.sync="dialogVisible"
|
|
||||||
width="50%"
|
|
||||||
:before-close="handleClose"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<el-form :model="addParams" ref="addForm">
|
|
||||||
<!-- v-if="isOverLimit" -->
|
|
||||||
<el-form-item :label="$t('backendSystem.broadcastContent')" prop="content">
|
|
||||||
<el-input
|
|
||||||
resize="none"
|
|
||||||
v-model="addParams.content"
|
|
||||||
type="textarea"
|
|
||||||
:rows="5"
|
|
||||||
@input="(val) => handleInput(val, 'add')"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span v-if="isOverLimit">
|
|
||||||
{{ $t("backendSystem.exceedingInput") }}</span
|
|
||||||
>
|
|
||||||
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('backendSystem.bthContent')" prop="buttonContent">
|
|
||||||
<el-input
|
|
||||||
resize="none"
|
|
||||||
v-model="addParams.buttonContent"
|
|
||||||
type="text"
|
|
||||||
|
|
||||||
/>
|
|
||||||
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('backendSystem.bthPath')" prop="buttonPath">
|
|
||||||
<el-input
|
|
||||||
resize="none"
|
|
||||||
v-model="addParams.buttonPath"
|
|
||||||
type="textarea"
|
|
||||||
:rows="2"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span v-if="isOverLimit">
|
|
||||||
{{ $t("backendSystem.exceedingInput") }}</span
|
|
||||||
>
|
|
||||||
<span> {{ $t("backendSystem.bthPathStandard") }}</span>
|
|
||||||
<el-button type="text" size="mini" @click="showPathHelp">
|
|
||||||
查看路径示例
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="handleClose">{{
|
|
||||||
$t("backendSystem.cancel")
|
|
||||||
}}</el-button>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
:loading="bthLoading"
|
|
||||||
@click="sureAddBroadcast"
|
|
||||||
>{{ $t("backendSystem.publish") }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 修改广播弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
:title="$t('backendSystem.editContent')"
|
|
||||||
:visible.sync="editDialogVisible"
|
|
||||||
width="50%"
|
|
||||||
:before-close="handleEditClose"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<el-form :model="editParams">
|
|
||||||
<el-form-item :label="$t('backendSystem.broadcastContent')">
|
|
||||||
<el-input
|
|
||||||
resize="none"
|
|
||||||
v-model="editParams.content"
|
|
||||||
type="textarea"
|
|
||||||
:rows="5"
|
|
||||||
@input="(val) => handleInput(val, 'edit')"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span v-if="isOverLimit">
|
|
||||||
{{ $t("backendSystem.exceedingInput") }}</span
|
|
||||||
>
|
|
||||||
<span> {{ $t("backendSystem.newlineInvalid") }}</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('backendSystem.bthContent')">
|
|
||||||
<el-input
|
|
||||||
v-model="editParams.buttonContent"
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('backendSystem.bthPath')">
|
|
||||||
<el-input
|
|
||||||
v-model="editParams.buttonPath"
|
|
||||||
type="textarea"
|
|
||||||
:rows="2"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 4px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>{{ $t("backendSystem.bthPathStandard") }}</span>
|
|
||||||
<el-button type="text" size="mini" @click="showPathHelp">
|
|
||||||
查看路径示例
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<div slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="handleEditClose">{{
|
|
||||||
$t("backendSystem.cancel")
|
|
||||||
}}</el-button>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
:loading="editLoading"
|
|
||||||
@click="sureEditBroadcast"
|
|
||||||
>{{ $t("backendSystem.editBroadcast") }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Index from "./index";
|
|
||||||
export default {
|
|
||||||
mixins: [Index],
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.main-title-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
background: #661ffb;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
margin-left: 28px;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 10px 20px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
.arrow {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.add-btn:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.main-title {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.elBtn {
|
|
||||||
background: #e60751;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
margin-left: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮内容和路径显示优化 */
|
|
||||||
.el-table .cell {
|
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 路径帮助弹窗样式 */
|
|
||||||
::v-deep .path-help-dialog {
|
|
||||||
.el-message-box__message {
|
|
||||||
white-space: pre-line;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 按钮标签样式优化 */
|
|
||||||
.el-tag {
|
|
||||||
max-width: 80px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 路径显示样式 */
|
|
||||||
.path-item {
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
background: #f5f7fa;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 3px;
|
|
||||||
margin: 1px 0;
|
|
||||||
border-left: 3px solid #409EFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-tag{
|
|
||||||
max-width: 200px !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
import { documentsList,findDataInfo} from '../../api/documentManagement'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地存储选中的问题ID的键名(常见问题页)
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
const SELECTED_PROBLEM_ID_KEY = 'commonProblem:selectedId'
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
problems: [
|
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// title: "如何开始挖矿?",
|
|
||||||
// content: "详细步骤:注册、配置矿机、连接矿池。",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 2,
|
|
||||||
// title: "如何查看收益?",
|
|
||||||
// content: "登录后在个人中心查看收益统计。",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 3,
|
|
||||||
// title: "如何联系客服?",
|
|
||||||
// content: "可通过在线客服或提交工单联系我们。",
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
listParams:{
|
|
||||||
type:"2",//常见问题
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:50
|
|
||||||
},
|
|
||||||
problemLoading:false,
|
|
||||||
DetailsParams:{
|
|
||||||
id:"",
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
},
|
|
||||||
info:""
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.fetchProblemsList(this.listParams)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchProblemsList(params) {
|
|
||||||
this.setLoading('problemLoading', true);
|
|
||||||
const res = await documentsList(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
this.problems = res.rows;
|
|
||||||
|
|
||||||
// 优先级:URL 参数 > 本地存储 > 列表首项
|
|
||||||
const routeId = this.$route && this.$route.query && this.$route.query.id ? String(this.$route.query.id) : ''
|
|
||||||
const savedId = this.getSavedSelectedId()
|
|
||||||
let resolvedId = routeId || savedId || ''
|
|
||||||
|
|
||||||
if (!resolvedId && this.problems && this.problems.length > 0) {
|
|
||||||
resolvedId = String(this.problems[0].id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolvedId) {
|
|
||||||
const existsInList = (this.problems || []).some(item => String(item.id) === String(resolvedId))
|
|
||||||
if (!existsInList && this.problems && this.problems.length > 0) {
|
|
||||||
resolvedId = String(this.problems[0].id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.DetailsParams.id = resolvedId
|
|
||||||
this.persistSelectedId(this.DetailsParams.id)
|
|
||||||
this.updateRouteQueryId(this.DetailsParams.id)
|
|
||||||
if (this.DetailsParams.id) {
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setLoading('problemLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchProblemDetails(params) {
|
|
||||||
this.setLoading('problemLoading', true);
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
console.log(res,"res");
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
}
|
|
||||||
this.setLoading('problemLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 跳转到问题详情页
|
|
||||||
* @param {number} id 问题ID
|
|
||||||
*/
|
|
||||||
handleClick(id) {
|
|
||||||
this.DetailsParams.id = id;
|
|
||||||
this.persistSelectedId(this.DetailsParams.id)
|
|
||||||
this.updateRouteQueryId(this.DetailsParams.id)
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将选中的问题ID持久化到本地存储
|
|
||||||
* @param {string|number} id 问题ID
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
persistSelectedId(id) {
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem(SELECTED_PROBLEM_ID_KEY, String(id))
|
|
||||||
} catch (error) {
|
|
||||||
console.error('persistSelectedId error', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取本地存储中保存的选中问题ID
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getSavedSelectedId() {
|
|
||||||
try {
|
|
||||||
return window.localStorage.getItem(SELECTED_PROBLEM_ID_KEY) || ''
|
|
||||||
} catch (error) {
|
|
||||||
console.error('getSavedSelectedId error', error)
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 replace 同步更新当前路由的查询参数中的 id
|
|
||||||
* 避免产生新的历史记录条目
|
|
||||||
* @param {string|number} id 问题ID
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
updateRouteQueryId(id) {
|
|
||||||
try {
|
|
||||||
if (!this.$route) return
|
|
||||||
const targetId = String(id)
|
|
||||||
const currentId = this.$route && this.$route.query && this.$route.query.id ? String(this.$route.query.id) : ''
|
|
||||||
if (currentId === targetId) return
|
|
||||||
|
|
||||||
const nextQuery = { ...(this.$route.query || {}), id: targetId }
|
|
||||||
if (this.$router && typeof this.$router.replace === 'function') {
|
|
||||||
const maybePromise = this.$router.replace({ query: nextQuery })
|
|
||||||
if (maybePromise && typeof maybePromise.catch === 'function') {
|
|
||||||
maybePromise.catch(() => {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('updateRouteQueryId error', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<section class="container">
|
|
||||||
<section class="leftNav">
|
|
||||||
<div
|
|
||||||
class="leftNav-item "
|
|
||||||
:class="{active:DetailsParams.id == item.id}"
|
|
||||||
v-for="item in problems"
|
|
||||||
:key="item.id"
|
|
||||||
@click="handleClick(item.id)"
|
|
||||||
@keydown.enter="handleClick(item.id)"
|
|
||||||
@keydown.space.prevent="handleClick(item.id)"
|
|
||||||
tabindex="0"
|
|
||||||
role="button"
|
|
||||||
:aria-label="item.title"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="rightContent">
|
|
||||||
<div v-if="problemLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{ $t('home.loadingContent') || '正在加载内容...' }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-else-if="info && info.trim()" class="dynamic-content" v-html="info"></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t('home.noContent') || '暂无内容' }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import IndexJs from "./index.js";
|
|
||||||
export default {
|
|
||||||
mixins: [IndexJs],
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.container{
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
width: 80vw;
|
|
||||||
height: 80vh;
|
|
||||||
margin: 0 auto;
|
|
||||||
// background: #fff;
|
|
||||||
border-radius: 10px;
|
|
||||||
// box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
padding: 20px;
|
|
||||||
margin-top: 60px;
|
|
||||||
padding-top: 50px;
|
|
||||||
.leftNav{
|
|
||||||
width: 260px;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 8px; // 预留滚动条空间,避免抖动
|
|
||||||
border-right: 1px solid #f1f2f3;
|
|
||||||
}
|
|
||||||
.rightContent{
|
|
||||||
flex: 1;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 32px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding-right: 20px;
|
|
||||||
.dynamic-content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
// 富文本样式
|
|
||||||
:deep(table) {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
:deep(p) {
|
|
||||||
line-height: 35px;
|
|
||||||
margin: 8px 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
:deep(th), :deep(td) {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
:deep(th) {
|
|
||||||
background: #f3f4f6;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
:deep(strong), :deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
:deep(em), :deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
:deep(a) {
|
|
||||||
color: #007bff !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(p) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: 2 !important;
|
|
||||||
margin: 0.8em 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(div) {
|
|
||||||
text-align: justify !important;
|
|
||||||
text-justify: inter-ideograph !important;
|
|
||||||
line-height: 2 !important;
|
|
||||||
margin: 0.8em 0 !important;
|
|
||||||
/* 英文按单词换行,避免拆词;超长连续单词在必要时断行 */
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: normal !important;
|
|
||||||
overflow-wrap: break-word !important; /* 现代浏览器 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
hyphens: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.loading-container {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
.loading-text {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #666;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.no-content {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #999;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.leftNav-item{
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
padding: 10px 14px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.5;
|
|
||||||
border-radius: 8px;
|
|
||||||
position: relative;
|
|
||||||
outline: none;
|
|
||||||
transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
|
|
||||||
|
|
||||||
&:hover{
|
|
||||||
background: #f7f7fb;
|
|
||||||
color: #4c36ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus-visible{
|
|
||||||
box-shadow: 0 0 0 3px rgba(101,31,255,0.2);
|
|
||||||
background: #f7f7fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active{
|
|
||||||
color: #4c36ff;
|
|
||||||
background: #f3f2ff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active::before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: -8px;
|
|
||||||
top: 8px;
|
|
||||||
bottom: 8px;
|
|
||||||
width: 3px;
|
|
||||||
background: #4c36ff;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 自定义滚动条 */
|
|
||||||
.leftNav::-webkit-scrollbar{
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
.leftNav::-webkit-scrollbar-thumb{
|
|
||||||
background: #e2e2e8;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
.leftNav:hover::-webkit-scrollbar-thumb{
|
|
||||||
background: #cfcfe7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
# 客服系统Socket连接优化说明
|
|
||||||
|
|
||||||
## 优化概述
|
|
||||||
|
|
||||||
本次优化采用**简洁的路由控制方案**,实现Socket连接的智能管理:
|
|
||||||
- **进入页面**:在`mounted`生命周期中自动建立Socket连接
|
|
||||||
- **离开页面**:在`beforeRouteLeave`路由守卫中立即断开所有Socket连接
|
|
||||||
|
|
||||||
## 核心功能
|
|
||||||
|
|
||||||
### 🎯 简洁实现
|
|
||||||
- **页面加载时**:自动建立Socket连接
|
|
||||||
- **路由离开时**:立即断开所有Socket连接
|
|
||||||
- **组件销毁时**:全面清理资源
|
|
||||||
|
|
||||||
## 技术实现
|
|
||||||
|
|
||||||
### 核心生命周期
|
|
||||||
|
|
||||||
#### `mounted` - 建立连接
|
|
||||||
```javascript
|
|
||||||
async mounted() {
|
|
||||||
// 获取聊天室列表
|
|
||||||
await this.fetchRoomList();
|
|
||||||
|
|
||||||
// 设置事件监听器
|
|
||||||
// ...其他初始化代码
|
|
||||||
|
|
||||||
// 添加存储变化监听
|
|
||||||
window.addEventListener("storage", this.handleStorageChange);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `beforeRouteLeave` - 断开连接
|
|
||||||
```javascript
|
|
||||||
beforeRouteLeave(to, from, next) {
|
|
||||||
console.log("🚪 离开客服页面,断开Socket连接");
|
|
||||||
this.disconnectWebSocket();
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `beforeDestroy` - 清理资源
|
|
||||||
```javascript
|
|
||||||
beforeDestroy() {
|
|
||||||
console.log("🧹 组件销毁,清理资源");
|
|
||||||
|
|
||||||
// 断开Socket连接
|
|
||||||
this.disconnectWebSocket();
|
|
||||||
|
|
||||||
// 清理定时器
|
|
||||||
// 移除事件监听
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用场景
|
|
||||||
|
|
||||||
### 1. 页面跳转 🚪
|
|
||||||
- 用户从任何页面进入客服页面:自动建立连接
|
|
||||||
- 用户从客服页面跳转到其他页面:立即断开连接
|
|
||||||
|
|
||||||
### 2. 浏览器操作 🔄
|
|
||||||
- 刷新页面:重新建立连接
|
|
||||||
- 关闭标签页:自动断开连接
|
|
||||||
|
|
||||||
### 3. 多窗口管理 🪟
|
|
||||||
- 每个窗口独立管理自己的连接
|
|
||||||
- 不会相互干扰
|
|
||||||
|
|
||||||
## 性能优势
|
|
||||||
|
|
||||||
### 1. **简洁高效** ⚡
|
|
||||||
- 代码量最少,逻辑最清晰
|
|
||||||
- 没有复杂的页面可见性检测
|
|
||||||
- 没有多余的活动时间监测
|
|
||||||
|
|
||||||
### 2. **资源节省** 💾
|
|
||||||
- 确保离开页面时立即断开连接
|
|
||||||
- 避免僵尸连接占用服务器资源
|
|
||||||
- 减少不必要的网络活动
|
|
||||||
|
|
||||||
### 3. **稳定可靠** 🛡️
|
|
||||||
- 路由级别的控制更加可靠
|
|
||||||
- 避免了复杂逻辑带来的潜在bug
|
|
||||||
- 易于维护和调试
|
|
||||||
|
|
||||||
## 关键代码
|
|
||||||
|
|
||||||
### Socket连接管理
|
|
||||||
```javascript
|
|
||||||
// 建立连接(在 created 中调用)
|
|
||||||
this.initWebSocket();
|
|
||||||
|
|
||||||
// 断开连接(在路由守卫中调用)
|
|
||||||
this.disconnectWebSocket();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 路由守卫
|
|
||||||
```javascript
|
|
||||||
beforeRouteLeave(to, from, next) {
|
|
||||||
console.log("🚪 离开客服页面,断开Socket连接");
|
|
||||||
this.disconnectWebSocket();
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 调试监控
|
|
||||||
|
|
||||||
### 控制台日志
|
|
||||||
```
|
|
||||||
🚪 离开客服页面,断开Socket连接
|
|
||||||
🧹 组件销毁,清理资源
|
|
||||||
🎉 [客服系统] WebSocket 连接成功
|
|
||||||
```
|
|
||||||
|
|
||||||
### 连接状态
|
|
||||||
- `isWebSocketConnected`: WebSocket连接状态
|
|
||||||
- `connectionStatus`: 应用层连接状态
|
|
||||||
|
|
||||||
## 优化亮点
|
|
||||||
|
|
||||||
### 1. **极简设计** ✨
|
|
||||||
- 移除了复杂的页面可见性检测
|
|
||||||
- 移除了用户活动时间监测
|
|
||||||
- 移除了多余的重连逻辑
|
|
||||||
|
|
||||||
### 2. **路由驱动** 🛣️
|
|
||||||
- 利用Vue Router的生命周期
|
|
||||||
- 在路由层面控制连接状态
|
|
||||||
- 更符合SPA应用的设计理念
|
|
||||||
|
|
||||||
### 3. **资源清理** 🧹
|
|
||||||
- 完善的组件销毁清理逻辑
|
|
||||||
- 确保没有内存泄漏
|
|
||||||
- 移除所有事件监听器
|
|
||||||
|
|
||||||
## 对比优势
|
|
||||||
|
|
||||||
| 特性 | 复杂方案 | 简洁方案 ✅ |
|
|
||||||
|------|---------|------------|
|
|
||||||
| 代码量 | 大量额外代码 | 最少必要代码 |
|
|
||||||
| 可维护性 | 复杂难维护 | 简单易维护 |
|
|
||||||
| 性能开销 | 需要监听多个事件 | 几乎无开销 |
|
|
||||||
| 可靠性 | 依赖浏览器API | 依赖路由机制 |
|
|
||||||
| 调试难度 | 复杂状态管理 | 简单直观 |
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **连接时机**:Socket连接在组件`created`时建立
|
|
||||||
2. **断开时机**:在路由离开时立即断开
|
|
||||||
3. **资源清理**:组件销毁时进行全面清理
|
|
||||||
4. **兼容性**:依赖Vue Router,适用于所有现代浏览器
|
|
||||||
|
|
||||||
## 总结
|
|
||||||
|
|
||||||
这个简洁的路由控制方案完美实现了用户的需求:
|
|
||||||
- ✅ **在当前页面才连接Socket**
|
|
||||||
- ✅ **离开页面就断开所有Socket连接**
|
|
||||||
- ✅ **不加多余代码,简洁实现**
|
|
||||||
|
|
||||||
通过移除复杂的页面可见性检测和用户活动监测,我们得到了一个更加稳定、高效、易维护的解决方案。
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
|||||||
import { findDataInfo } from "../../../api/documentManagement"
|
|
||||||
export default{
|
|
||||||
data(){
|
|
||||||
return{
|
|
||||||
typeArray:[],
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
// this.fetchDataInfo()
|
|
||||||
|
|
||||||
|
|
||||||
// if (this.$route.query.id) {
|
|
||||||
// this.fetchDataInfo({id:this.$route.query.id})
|
|
||||||
// }
|
|
||||||
|
|
||||||
},
|
|
||||||
methods:{
|
|
||||||
async fetchDataInfo(params){
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if (res && res.code === 200) {
|
|
||||||
this.modifyData = res.data
|
|
||||||
this.addParams = this.modifyData
|
|
||||||
// 确保type字段为字符串类型,以便与TypeList中的value匹配
|
|
||||||
this.addParams.type = String(this.addParams.type)
|
|
||||||
this.addParams.childType = String(this.addParams.childType)
|
|
||||||
this.typeArray = [this.addParams.type]
|
|
||||||
// 标记已从后台获取数据,避免被本地存储覆盖
|
|
||||||
this.hasBackendData = true
|
|
||||||
// 强制用接口数据刷新编辑器内容
|
|
||||||
if (this.editor && this.addParams.content) {
|
|
||||||
this.editor.txt.html(this.addParams.content)
|
|
||||||
this.html = this.addParams.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 币种选择变更处理
|
|
||||||
* @param {string} scope - 选择的币种
|
|
||||||
*/
|
|
||||||
changeScreen(scope) {
|
|
||||||
let brand = scope
|
|
||||||
for (let index in this.currencyList) {
|
|
||||||
let aa = this.currencyList[index];
|
|
||||||
let value = aa.value;
|
|
||||||
if (brand === value) {
|
|
||||||
this.$refs.screen.$el.children[0].children[0].setAttribute('style', "background:url(" + aa.imgUrl + ") no-repeat 10PX;background-size: 20PX 20PX;color:#333;padding-left: 33PX;");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存用户选择的币种到localStorage
|
|
||||||
localStorage.setItem('userManagement_selectedCurrency', scope);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
handleClearScreen(){
|
|
||||||
// 清除币种图片样式
|
|
||||||
if (this.$refs.screen && this.$refs.screen.$el) {
|
|
||||||
this.$refs.screen.$el.children[0].children[0].style.background = '';
|
|
||||||
this.$refs.screen.$el.children[0].children[0].style.paddingLeft = '';
|
|
||||||
}
|
|
||||||
// 也可以清除 localStorage 里的币种选择
|
|
||||||
localStorage.removeItem('userManagement_selectedCurrency');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,471 +0,0 @@
|
|||||||
import { getListDataByPage, addDocument, deleteDocument, documentsList, findDataInfo, updateDocument } from '../../api/documentManagement'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
tableData: [
|
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// createTime: "2025-06-24 10:00:00",
|
|
||||||
// content: "内isjisjfidjfjfjffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff容",
|
|
||||||
// createUser: "创建人",
|
|
||||||
// updateTime: "2025-06-24 10:00:00",
|
|
||||||
// updateUser: "修改人",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 2,
|
|
||||||
// createTime: "2025-06-24 10:00:00",
|
|
||||||
// content: "内容",
|
|
||||||
// createUser: "创建人",
|
|
||||||
// updateTime: "2025-06-24 10:00:00",
|
|
||||||
// updateUser: "修改人",
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
listParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 50,
|
|
||||||
keyword:"",
|
|
||||||
lang:"",
|
|
||||||
type:"",
|
|
||||||
},
|
|
||||||
addParams: {
|
|
||||||
content: "",
|
|
||||||
buttonContent: "",
|
|
||||||
buttonPath: "",
|
|
||||||
},
|
|
||||||
editParams: {
|
|
||||||
content: "",
|
|
||||||
id: "",
|
|
||||||
buttonContent: "",
|
|
||||||
buttonPath: "",
|
|
||||||
},
|
|
||||||
dialogVisible: false,
|
|
||||||
bthLoading: false,
|
|
||||||
documentLoading: false,
|
|
||||||
editDialogVisible: false,
|
|
||||||
editLoading: false,
|
|
||||||
byteCount: "",
|
|
||||||
isOverLimit: false,
|
|
||||||
total: 0,
|
|
||||||
pageSizes: [50, 100, 300],
|
|
||||||
currentPage: 1,
|
|
||||||
TypeList:[
|
|
||||||
{//挖矿教程
|
|
||||||
value:"1",
|
|
||||||
label:"backendSystem.miningTutorial",
|
|
||||||
articleUrl:"AccessMiningPool"
|
|
||||||
},
|
|
||||||
{//常见问题
|
|
||||||
value:"2",
|
|
||||||
label:"backendSystem.commonProblems",
|
|
||||||
articleUrl:"commonProblem"
|
|
||||||
},
|
|
||||||
{//公告中心
|
|
||||||
value:"3",
|
|
||||||
label:"backendSystem.announcementCenter",
|
|
||||||
articleUrl:"announcements"
|
|
||||||
},
|
|
||||||
{//其他
|
|
||||||
value:"0",
|
|
||||||
label:"backendSystem.other",
|
|
||||||
articleUrl:"",
|
|
||||||
children:[{
|
|
||||||
value:"1",
|
|
||||||
label:"home.serviceTerms",
|
|
||||||
articleUrl:"serviceTerms"
|
|
||||||
},{
|
|
||||||
value:"2",
|
|
||||||
label:"home.rate",
|
|
||||||
articleUrl:"rate"
|
|
||||||
},{
|
|
||||||
value:"3",
|
|
||||||
label:"home.APIfile",
|
|
||||||
articleUrl:"apiFile"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
],
|
|
||||||
queryParams:{
|
|
||||||
keyword:"",
|
|
||||||
type:"",
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$addStorageEvent(1, "TypeList", JSON.stringify(this.TypeList));
|
|
||||||
this.listParams.lang = this.$i18n.locale
|
|
||||||
let token
|
|
||||||
try {
|
|
||||||
token = JSON.parse(localStorage.getItem('token'))
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
if (token) {
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchListData(params) {
|
|
||||||
|
|
||||||
this.setLoading('documentLoading', true);
|
|
||||||
const res = await getListDataByPage(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.tableData = res.rows
|
|
||||||
this.total = res.total
|
|
||||||
}
|
|
||||||
this.setLoading('documentLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchUpdateDocument(params) {
|
|
||||||
this.setLoading('editLoading', true);
|
|
||||||
|
|
||||||
// 发送请求前打印参数,用于调试
|
|
||||||
console.log('发送编辑广播请求的参数:', params);
|
|
||||||
|
|
||||||
const res = await updateDocument(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$message.success(this.$t("backendSystem.editSuccess"))
|
|
||||||
this.editDialogVisible = false;
|
|
||||||
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
}
|
|
||||||
this.setLoading('editLoading', false);
|
|
||||||
},
|
|
||||||
async deleteDocument(params) {
|
|
||||||
const res = await deleteDocument(params)
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.$message.success(this.$t("backendSystem.deleteSuccess"))
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handelAddDocument(){
|
|
||||||
const lang = this.$i18n.locale
|
|
||||||
this.$router.push(`/${lang}/addDocument`)
|
|
||||||
},
|
|
||||||
handleClose() {
|
|
||||||
this.dialogVisible = false;
|
|
||||||
this.addParams.content = ""
|
|
||||||
this.addParams.buttonContent = ""
|
|
||||||
this.addParams.buttonPath = ""
|
|
||||||
this.setLoading('bthLoading', false);
|
|
||||||
},
|
|
||||||
sureAddBroadcast() {
|
|
||||||
|
|
||||||
this.addParams.content = this.addParams.content.trim()
|
|
||||||
this.addParams.content = this.addParams.content.replace(/[\r\n]/g, '');
|
|
||||||
this.addParams.buttonPath = this.addParams.buttonPath.trim()
|
|
||||||
this.addParams.buttonPath = this.addParams.buttonPath.replace(/[\r\n]/g, '');
|
|
||||||
if (!this.addParams.content) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.addParams.buttonContent && this.addParams.buttonPath) || (!this.addParams.buttonContent && !this.addParams.buttonPath)) {
|
|
||||||
|
|
||||||
if (this.addParams.buttonPath) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
let pathArray = this.addParams.buttonPath.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (this.addParams.buttonContent) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
let pathArray2 = this.addParams.buttonContent.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray2.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray2.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (this.addParams.buttonContent && this.addParams.buttonPath) {
|
|
||||||
if (pathArray.length !== pathArray2.length) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证每个路径是否有效
|
|
||||||
const invalidPaths = pathArray.filter(path => !isValidPath(path));
|
|
||||||
if (invalidPaths.length > 0) {
|
|
||||||
const suggestions = getPathSuggestions(invalidPaths[0]);
|
|
||||||
this.$message.error(`${this.$t("backendSystem.invalidPath")}: ${invalidPaths.join(', ')}。${this.$t("backendSystem.invalidPathSuggestions")}: ${suggestions.slice(0, 3).join(', ')}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证通过,保持字符串格式传给后端(不转换为数组)
|
|
||||||
// this.addParams.buttonPath 保持原始字符串格式
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.addBroadcast(this.addParams);
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
surefetchUpdateDocument() {
|
|
||||||
this.editParams.content = this.editParams.content.trim()
|
|
||||||
this.editParams.content = this.editParams.content.replace(/[\r\n]/g, '');
|
|
||||||
let buttonContentArray
|
|
||||||
let pathArray
|
|
||||||
if (!this.editParams.content) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputContent"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.editParams.buttonContent) {
|
|
||||||
this.editParams.buttonContent = this.editParams.buttonContent.trim().replace(/[\r\n]/g, '');
|
|
||||||
|
|
||||||
// 验证按钮内容和路径是否匹配
|
|
||||||
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
|
|
||||||
if (this.editParams.buttonContent) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
buttonContentArray = this.editParams.buttonContent.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (buttonContentArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (buttonContentArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有按钮路径,进行验证
|
|
||||||
if (this.editParams.buttonPath) {
|
|
||||||
this.editParams.buttonPath = this.editParams.buttonPath.trim().replace(/[\r\n]/g, '');
|
|
||||||
|
|
||||||
// 验证按钮内容和路径是否匹配
|
|
||||||
if ((this.editParams.buttonContent && this.editParams.buttonPath) || (!this.editParams.buttonContent && !this.editParams.buttonPath)) {
|
|
||||||
if (this.editParams.buttonPath) {
|
|
||||||
// 兼容中英文逗号分割
|
|
||||||
pathArray = this.editParams.buttonPath.split(/[,,]/).map(e => e.trim()).filter(e => e);
|
|
||||||
if (pathArray.length > 5) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.max5"))
|
|
||||||
return
|
|
||||||
} else if (pathArray.length === 0) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证每个路径是否有效
|
|
||||||
const invalidPaths = pathArray.filter(path => !isValidPath(path));
|
|
||||||
if (invalidPaths.length > 0) {
|
|
||||||
const suggestions = getPathSuggestions(invalidPaths[0]);
|
|
||||||
this.$message.error(`${this.$t("backendSystem.invalidPath")}: ${invalidPaths.join(', ')}。${this.$t("backendSystem.invalidPathSuggestions")}: ${suggestions.slice(0, 3).join(', ')}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.editParams.buttonContent && this.editParams.buttonPath) {
|
|
||||||
if (buttonContentArray.length !== pathArray.length) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pathNumberNotMatch"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputButtonContentAndPath"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.fetchUpdateDocument(this.editParams);
|
|
||||||
},
|
|
||||||
handleEdit(row) {
|
|
||||||
this.$router.push({
|
|
||||||
path: `/${this.$i18n.locale}/modifyDocument`,
|
|
||||||
query: {
|
|
||||||
id: row.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleEditClose() {
|
|
||||||
this.editDialogVisible = false;
|
|
||||||
this.editParams.content = ""
|
|
||||||
this.editParams.buttonContent = ""
|
|
||||||
this.editParams.buttonPath = ""
|
|
||||||
this.setLoading('editLoading', false);
|
|
||||||
},
|
|
||||||
handelDelete(row) {
|
|
||||||
this.deleteDocument({ id: row.id });
|
|
||||||
},
|
|
||||||
getUtf8Bytes(str) {
|
|
||||||
let bytes = 0;
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
|
||||||
const code = str.charCodeAt(i);
|
|
||||||
if (code <= 0x7f) bytes += 1;
|
|
||||||
else if (code <= 0x7ff) bytes += 2;
|
|
||||||
else if (code <= 0xffff) bytes += 3;
|
|
||||||
else bytes += 4;
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleInput(val, type = 'add') {
|
|
||||||
let bytes = this.getUtf8Bytes(val);
|
|
||||||
if (bytes > 100) {
|
|
||||||
this.isOverLimit = true;
|
|
||||||
// 截断到100字节
|
|
||||||
let newVal = '';
|
|
||||||
let total = 0;
|
|
||||||
for (let ch of val) {
|
|
||||||
let chBytes = this.getUtf8Bytes(ch);
|
|
||||||
if (total + chBytes > 100) break;
|
|
||||||
newVal += ch;
|
|
||||||
total += chBytes;
|
|
||||||
}
|
|
||||||
if (type === 'add') {
|
|
||||||
this.addParams.content = newVal;
|
|
||||||
} else {
|
|
||||||
this.editParams.content = newVal;
|
|
||||||
}
|
|
||||||
bytes = total;
|
|
||||||
} else {
|
|
||||||
this.isOverLimit = false;
|
|
||||||
if (type === 'add') {
|
|
||||||
this.addParams.content = val;
|
|
||||||
} else {
|
|
||||||
this.editParams.content = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.byteCount = bytes;
|
|
||||||
},
|
|
||||||
|
|
||||||
handelTime(time) {
|
|
||||||
return `${time.split("T")[0]} ${time.split("T")[1]}`
|
|
||||||
},
|
|
||||||
handleSizeChange(val) {
|
|
||||||
|
|
||||||
this.listParams.pageSize = val
|
|
||||||
this.listParams.pageNum = 1
|
|
||||||
this.currentPage = 1
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
|
|
||||||
},
|
|
||||||
handleCurrentChange(val) {
|
|
||||||
|
|
||||||
this.listParams.pageNum = val
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取有效路径建议信息
|
|
||||||
* @returns {Array} 路径建议列表
|
|
||||||
*/
|
|
||||||
getValidPathSuggestions() {
|
|
||||||
return getPathSuggestions('').slice(0, 8); // 返回前8个常用路径
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示路径使用帮助
|
|
||||||
*/
|
|
||||||
showPathHelp() {
|
|
||||||
const suggestions = this.getValidPathSuggestions();
|
|
||||||
const helpMessage = `
|
|
||||||
常用路径示例:
|
|
||||||
${suggestions.slice(0, 10).join('\n')}
|
|
||||||
|
|
||||||
路径规则:
|
|
||||||
• 多个路径用逗号分隔
|
|
||||||
• 路径必须以 / 开头
|
|
||||||
• 支持动态路由参数
|
|
||||||
• 不要包含域名,只写路径部分
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.$alert(helpMessage, '路径格式说明', {
|
|
||||||
confirmButtonText: '知道了',
|
|
||||||
type: 'info',
|
|
||||||
customClass: 'path-help-dialog'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化按钮内容显示
|
|
||||||
* @param {string} buttonContent - 逗号分隔的按钮内容字符串
|
|
||||||
* @returns {Array} 按钮内容数组
|
|
||||||
*/
|
|
||||||
formatButtonContent(buttonContent) {
|
|
||||||
if (!buttonContent || typeof buttonContent !== 'string') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return buttonContent
|
|
||||||
.split(',')
|
|
||||||
.map(btn => btn.trim())
|
|
||||||
.filter(btn => btn);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化按钮路径显示
|
|
||||||
* @param {string} buttonPath - 逗号分隔的路径字符串
|
|
||||||
* @returns {Array} 路径数组
|
|
||||||
*/
|
|
||||||
formatButtonPath(buttonPath) {
|
|
||||||
if (!buttonPath || typeof buttonPath !== 'string') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return buttonPath
|
|
||||||
.split(',')
|
|
||||||
.map(path => path.trim())
|
|
||||||
.filter(path => path);
|
|
||||||
},
|
|
||||||
|
|
||||||
handelType(type){
|
|
||||||
try {
|
|
||||||
let label = this.TypeList.find(item => item.value == type).label
|
|
||||||
return this.$t(label)
|
|
||||||
} catch (error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeScreen(type){
|
|
||||||
this.listParams.type = type
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
},
|
|
||||||
handelQuery(){
|
|
||||||
this.listParams.keyword = this.queryParams.keyword
|
|
||||||
if (!this.listParams.keyword) {
|
|
||||||
this.$message.warning(this.$t("backendSystem.pleaseInputKeyword"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
},
|
|
||||||
handleInputClear(){
|
|
||||||
this.listParams.keyword = this.queryParams.keyword
|
|
||||||
this.fetchListData(this.listParams);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-loading="documentLoading">
|
|
||||||
<div class="main-title-box">
|
|
||||||
<div class="main-title">{{ $t("backendSystem.documentManagement") }}</div>
|
|
||||||
<el-button class="add-btn" @click="handelAddDocument"
|
|
||||||
>{{ $t("backendSystem.addDocument") }}
|
|
||||||
<i class="iconfont icon-youjiantou1 arrow"></i
|
|
||||||
></el-button>
|
|
||||||
</div>
|
|
||||||
<el-form
|
|
||||||
:inline="true"
|
|
||||||
:model="queryParams"
|
|
||||||
class="demo-form-inline"
|
|
||||||
ref="formRef"
|
|
||||||
>
|
|
||||||
<el-form-item :label="$t('backendSystem.documentType')|| '文档类型'" prop="type">
|
|
||||||
<el-select
|
|
||||||
class="input"
|
|
||||||
clearable
|
|
||||||
size="middle"
|
|
||||||
ref="screen"
|
|
||||||
@change="changeScreen(queryParams.type)"
|
|
||||||
v-model="queryParams.type"
|
|
||||||
:placeholder="$t(`backendSystem.pleaseSelect`)"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in TypeList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="$t(item.label)"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
<div style="display: flex; align-items: center">
|
|
||||||
<img :src="item.imgUrl" style="float: left; width: 20px" />
|
|
||||||
<span style="float: left; margin-left: 5px">
|
|
||||||
{{ $t(item.label) }}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('backendSystem.search')|| '搜索'" style="margin-left: 5vw" prop="minerUser">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.keyword"
|
|
||||||
:placeholder="$t('backendSystem.pleaseInput')"
|
|
||||||
clearable
|
|
||||||
@clear="handleInputClear"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item style="margin-left: 1vw">
|
|
||||||
<el-button type="primary" @click="handelQuery">{{
|
|
||||||
$t("backendSystem.query")
|
|
||||||
}}</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table
|
|
||||||
:data="tableData"
|
|
||||||
border
|
|
||||||
style="width: 100%; margin-bottom: 18px"
|
|
||||||
:header-cell-style="{ 'text-align': 'center' }"
|
|
||||||
:cell-style="{ 'text-align': 'center' }"
|
|
||||||
height="60vh"
|
|
||||||
>
|
|
||||||
<el-table-column prop="id" label="ID" width="60" />
|
|
||||||
<el-table-column
|
|
||||||
prop="createTime"
|
|
||||||
:label="$t('backendSystem.createTime')|| '创建时间'"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.createTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
prop="createUser"
|
|
||||||
:label="$t('backendSystem.createUser')|| '创建人'"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column prop="content" :label="$t('backendSystem.content')|| '文档内容'" show-overflow-tooltip />
|
|
||||||
<el-table-column
|
|
||||||
prop="title"
|
|
||||||
:label="$t('backendSystem.documentTitle')|| '文档标题'"
|
|
||||||
width="200"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="type"
|
|
||||||
:label="$t('backendSystem.documentType')|| '文档类型'"
|
|
||||||
width="100"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelType(scope.row.type) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column
|
|
||||||
prop="updateTime"
|
|
||||||
:label="$t('backendSystem.updateTime')|| '修改时间'"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ handelTime(scope.row.updateTime) }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="updateUser"
|
|
||||||
:label="$t('backendSystem.updateUser')|| '修改人'"
|
|
||||||
width="160"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-table-column :label="$t('backendSystem.operation')" width="160">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" @click="handleEdit(scope.row)">{{
|
|
||||||
$t("backendSystem.edit")
|
|
||||||
}}</el-button>
|
|
||||||
|
|
||||||
<el-popconfirm
|
|
||||||
:confirm-button-text="$t(`work.confirm`)"
|
|
||||||
:cancel-button-text="$t(`work.cancel`)"
|
|
||||||
icon="el-icon-info"
|
|
||||||
icon-color="red"
|
|
||||||
:title="$t(`alerts.deleteRemind`)"
|
|
||||||
@confirm="handelDelete(scope.row)"
|
|
||||||
>
|
|
||||||
<el-button class="elBtn" size="mini" slot="reference">{{
|
|
||||||
$t(`personal.delete`)
|
|
||||||
}}</el-button>
|
|
||||||
</el-popconfirm>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24" style="display: flex; justify-content: center">
|
|
||||||
<el-pagination
|
|
||||||
style="margin: 0 auto;"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page.sync="currentPage"
|
|
||||||
:page-sizes="pageSizes"
|
|
||||||
:page-size="listParams.pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total"
|
|
||||||
>
|
|
||||||
</el-pagination>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Index from "./index";
|
|
||||||
export default {
|
|
||||||
mixins: [Index],
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.main-title-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
background: #661ffb;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
margin-left: 28px;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 10px 20px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
.arrow {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.add-btn:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.main-title {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.elBtn {
|
|
||||||
background: #e60751;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
margin-left: 18px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import { findDataInfo } from "../../../api/documentManagement"
|
|
||||||
export default{
|
|
||||||
data(){
|
|
||||||
return{
|
|
||||||
typeArray:[],
|
|
||||||
currencyList: [],
|
|
||||||
screenCurrency: "",
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
// this.fetchDataInfo()
|
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"));
|
|
||||||
window.addEventListener("setItem", () => {
|
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"));
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.$route.query.id) {
|
|
||||||
this.fetchDataInfo({id:this.$route.query.id})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
methods:{
|
|
||||||
async fetchDataInfo(params){
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if (res && res.code === 200) {
|
|
||||||
this.modifyData = res.data
|
|
||||||
this.addParams = this.modifyData
|
|
||||||
// 确保type字段为字符串类型,以便与TypeList中的value匹配
|
|
||||||
this.addParams.type = String(this.addParams.type)
|
|
||||||
this.addParams.childType = String(this.addParams.childType)
|
|
||||||
|
|
||||||
if (this.modifyData.childType && this.modifyData.childType !== `0`) {
|
|
||||||
this.typeArray = [this.addParams.type,this.modifyData.childType]
|
|
||||||
|
|
||||||
|
|
||||||
}else{
|
|
||||||
this.typeArray = [this.modifyData.type]
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
// 标记已从后台获取数据,避免被本地存储覆盖
|
|
||||||
this.hasBackendData = true
|
|
||||||
this.screenCurrency = this.addParams.coin
|
|
||||||
// 强制用接口数据刷新编辑器内容
|
|
||||||
if (this.editor && this.addParams.content) {
|
|
||||||
this.editor.txt.html(this.addParams.content)
|
|
||||||
this.html = this.addParams.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 币种选择变更处理
|
|
||||||
* @param {string} scope - 选择的币种
|
|
||||||
*/
|
|
||||||
changeScreen(scope) {
|
|
||||||
let brand = scope
|
|
||||||
for (let index in this.currencyList) {
|
|
||||||
let aa = this.currencyList[index];
|
|
||||||
let value = aa.value;
|
|
||||||
if (brand === value) {
|
|
||||||
this.$refs.screen.$el.children[0].children[0].setAttribute('style', "background:url(" + aa.imgUrl + ") no-repeat 10PX;background-size: 20PX 20PX;color:#333;padding-left: 33PX;");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存用户选择的币种到localStorage
|
|
||||||
localStorage.setItem('userManagement_selectedCurrency', scope);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,760 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="editor-page">
|
|
||||||
<!-- 页面头部 -->
|
|
||||||
<div class="page-header">
|
|
||||||
<div class="header-left">
|
|
||||||
<div class="title-section">
|
|
||||||
<i class="el-icon-edit-outline title-icon"></i>
|
|
||||||
<h1 class="page-title">wangeditor 富文本文档编辑器</h1>
|
|
||||||
</div>
|
|
||||||
<p class="page-description">使用富文本编辑器创建和管理文档,支持文本格式化、链接、列表等功能</p>
|
|
||||||
</div>
|
|
||||||
<div class="header-actions">
|
|
||||||
<el-button type="info" icon="el-icon-view" @click="handlePreview">
|
|
||||||
预览文档
|
|
||||||
</el-button>
|
|
||||||
<el-button type="success" icon="el-icon-document" @click="handleSave">
|
|
||||||
保存文档
|
|
||||||
</el-button>
|
|
||||||
<el-button type="warning" icon="el-icon-upload2" @click="handelAddDocument">
|
|
||||||
发布文档
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 文档配置区域 -->
|
|
||||||
<div class="config-section">
|
|
||||||
<div class="section-header">
|
|
||||||
<i class="el-icon-setting"></i>
|
|
||||||
<span>文档配置</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="config-content">
|
|
||||||
<div class="config-row">
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="required">文档标题</label>
|
|
||||||
<el-input
|
|
||||||
v-model="addParams.title"
|
|
||||||
placeholder="请输入文档标题"
|
|
||||||
@input="handleAutoSave"
|
|
||||||
size="medium"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="config-item">
|
|
||||||
<label class="required">文档类型</label>
|
|
||||||
<el-select
|
|
||||||
v-model="addParams.type"
|
|
||||||
placeholder="请选择文档类型"
|
|
||||||
@change="handleAutoSave"
|
|
||||||
size="medium"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in TypeList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value">
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 编辑器区域 -->
|
|
||||||
<div class="editor-section">
|
|
||||||
<div class="section-header">
|
|
||||||
<i class="el-icon-edit-outline"></i>
|
|
||||||
<span>富文本编辑器</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="editor-container">
|
|
||||||
<Toolbar
|
|
||||||
:editor="editor"
|
|
||||||
:defaultConfig="toolbarConfig"
|
|
||||||
:mode="mode"
|
|
||||||
style="border-bottom: 1px solid #ccc"
|
|
||||||
/>
|
|
||||||
<Editor
|
|
||||||
style="height: 600px; overflow-y: hidden;"
|
|
||||||
v-model="addParams.content"
|
|
||||||
:defaultConfig="editorConfig"
|
|
||||||
:mode="mode"
|
|
||||||
@onCreated="onCreated"
|
|
||||||
@onChange="handleEditorChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 预览文档对话框 -->
|
|
||||||
<el-dialog
|
|
||||||
title="文档预览"
|
|
||||||
:visible.sync="previewVisible"
|
|
||||||
width="80%"
|
|
||||||
:before-close="handlePreviewClose"
|
|
||||||
class="preview-dialog"
|
|
||||||
>
|
|
||||||
<div class="preview-content">
|
|
||||||
<div v-html="addParams.content"></div>
|
|
||||||
|
|
||||||
<div v-if="!addParams.content" class="preview-empty">
|
|
||||||
<i class="el-icon-document"></i>
|
|
||||||
<p>暂无内容</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="previewVisible = false">关闭</el-button>
|
|
||||||
<el-button type="primary" @click="handlePrintPreview">打印预览</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Vue from "vue";
|
|
||||||
import E from "wangeditor";
|
|
||||||
import { addDocument } from '../api/documentManagement'
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
components: { Editor, Toolbar },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
editor: null,
|
|
||||||
html: '<p>hello</p>',
|
|
||||||
toolbarConfig: {
|
|
||||||
excludeKeys: [],
|
|
||||||
insertKeys: {
|
|
||||||
index: 0,
|
|
||||||
keys: ['bold', 'italic', 'underline', 'through', 'code', 'sub', 'sup', 'clearStyle']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
editorConfig: {
|
|
||||||
placeholder: '请在此输入文档内容...',
|
|
||||||
MENU_CONF: {}
|
|
||||||
},
|
|
||||||
mode: 'default',
|
|
||||||
addParams:{
|
|
||||||
title:'',
|
|
||||||
content:'',
|
|
||||||
type:'',
|
|
||||||
lang:"",
|
|
||||||
imageUrl: '',
|
|
||||||
},
|
|
||||||
lastSaveTime: '',
|
|
||||||
autoSaveTimer: null,
|
|
||||||
isSaving: false, // 新增:控制自动保存提示的显示
|
|
||||||
previewVisible: false, // 新增:控制预览对话框的显示
|
|
||||||
currentTime: '', // 新增:记录预览时间
|
|
||||||
TypeList:[
|
|
||||||
// {
|
|
||||||
// value:"1",
|
|
||||||
// label:"服务条款"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value:"2",
|
|
||||||
// label:"api文档"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value:"3",
|
|
||||||
// label:"挖矿教程"
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value:"0",
|
|
||||||
// label:"其他"
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchAddDocument(params){
|
|
||||||
const res = await addDocument(params)
|
|
||||||
},
|
|
||||||
|
|
||||||
onCreated(editor) {
|
|
||||||
this.editor = Object.seal(editor)
|
|
||||||
|
|
||||||
// 编辑器创建后,如果有恢复的内容,设置到编辑器中
|
|
||||||
if (this.addParams.content) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
editor.setHtml(this.addParams.content)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handelAddDocument(){
|
|
||||||
if (!this.addParams.type) {
|
|
||||||
this.$message({
|
|
||||||
message: '请填写文档类型',
|
|
||||||
type: 'warning',
|
|
||||||
duration: 4000,
|
|
||||||
showClose: true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchAddDocument(this.addParams)
|
|
||||||
},
|
|
||||||
|
|
||||||
handlePreview() {
|
|
||||||
this.previewVisible = true
|
|
||||||
this.currentTime = new Date().toLocaleString('zh-CN', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: '2-digit',
|
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
handlePreviewClose() {
|
|
||||||
this.previewVisible = false
|
|
||||||
},
|
|
||||||
|
|
||||||
handlePrintPreview() {
|
|
||||||
const printWindow = window.open('', '_blank');
|
|
||||||
if (printWindow) {
|
|
||||||
printWindow.document.write(`
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>${this.addParams.title || '文档预览'}</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: 'Arial', sans-serif;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #333;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
.preview-empty {
|
|
||||||
text-align: center;
|
|
||||||
padding: 50px 0;
|
|
||||||
color: #95a5a6;
|
|
||||||
}
|
|
||||||
.preview-empty i {
|
|
||||||
font-size: 40px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
${this.addParams.content || '<div class="preview-empty"><i>📄</i><p>暂无内容</p></div>'}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`);
|
|
||||||
printWindow.document.close();
|
|
||||||
printWindow.print();
|
|
||||||
printWindow.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSave() {
|
|
||||||
this.manualSave()
|
|
||||||
this.$message({
|
|
||||||
message: '内容已保存到本地,请尽快发布,关闭页面可能丢失内容',
|
|
||||||
type: 'success',
|
|
||||||
duration: 4000,
|
|
||||||
showClose: true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEditorChange() {
|
|
||||||
this.handleAutoSave()
|
|
||||||
},
|
|
||||||
|
|
||||||
handleAutoSave() {
|
|
||||||
// 显示正在保存状态
|
|
||||||
this.isSaving = true
|
|
||||||
|
|
||||||
if (this.autoSaveTimer) {
|
|
||||||
clearTimeout(this.autoSaveTimer)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.autoSaveTimer = setTimeout(() => {
|
|
||||||
this.saveToLocalStorage()
|
|
||||||
}, 1500) // 减少到1.5秒,提高响应速度
|
|
||||||
},
|
|
||||||
|
|
||||||
saveToLocalStorage() {
|
|
||||||
try {
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveData = {
|
|
||||||
title: this.addParams.title,
|
|
||||||
content: this.addParams.content,
|
|
||||||
type: this.addParams.type,
|
|
||||||
imageUrl: this.addParams.imageUrl,
|
|
||||||
timestamp: new Date().toLocaleString('zh-CN', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: '2-digit',
|
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit'
|
|
||||||
}),
|
|
||||||
lastModified: Date.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem('editor_draft', JSON.stringify(saveData))
|
|
||||||
this.lastSaveTime = saveData.timestamp
|
|
||||||
this.isSaving = false
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('自动保存失败:', error)
|
|
||||||
this.isSaving = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
loadFromLocalStorage() {
|
|
||||||
try {
|
|
||||||
const savedData = localStorage.getItem('editor_draft')
|
|
||||||
if (savedData) {
|
|
||||||
const data = JSON.parse(savedData)
|
|
||||||
|
|
||||||
// 检查数据是否过期(7天)
|
|
||||||
const isExpired = Date.now() - (data.lastModified || 0) > 7 * 24 * 60 * 60 * 1000
|
|
||||||
|
|
||||||
if (isExpired) {
|
|
||||||
console.log('本地数据已过期,清除缓存')
|
|
||||||
localStorage.removeItem('editor_draft')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 $nextTick 确保 DOM 更新后再设置内容
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.addParams.title = data.title || ''
|
|
||||||
this.addParams.content = data.content || ''
|
|
||||||
this.addParams.type = data.type || '1'
|
|
||||||
this.addParams.imageUrl = data.imageUrl || ''
|
|
||||||
this.lastSaveTime = data.timestamp || ''
|
|
||||||
|
|
||||||
// 如果编辑器已经创建,直接设置内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.editor.setHtml(data.content || '')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('恢复数据失败:', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
clearDraft() {
|
|
||||||
localStorage.removeItem('editor_draft')
|
|
||||||
this.lastSaveTime = ''
|
|
||||||
this.isSaving = false
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新增:手动保存方法
|
|
||||||
manualSave() {
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
this.saveToLocalStorage()
|
|
||||||
},
|
|
||||||
|
|
||||||
// 页面卸载前处理
|
|
||||||
handleBeforeUnload(event) {
|
|
||||||
// 自动保存,不提示用户
|
|
||||||
if (this.addParams.title || this.addParams.content) {
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
this.saveToLocalStorage()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 新增:获取文档类型名称
|
|
||||||
getDocumentTypeName(type) {
|
|
||||||
switch (type) {
|
|
||||||
case '1':
|
|
||||||
return '服务条款';
|
|
||||||
case '2':
|
|
||||||
return 'api文档';
|
|
||||||
case '3':
|
|
||||||
return '挖矿教程';
|
|
||||||
case '0':
|
|
||||||
return '其他';
|
|
||||||
default:
|
|
||||||
return '未知类型';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
// 先恢复数据
|
|
||||||
this.loadFromLocalStorage()
|
|
||||||
|
|
||||||
// 添加页面卸载前的保存保护
|
|
||||||
window.addEventListener('beforeunload', this.handleBeforeUnload)
|
|
||||||
|
|
||||||
// 延迟设置默认内容,避免覆盖恢复的数据
|
|
||||||
setTimeout(() => {
|
|
||||||
if (!this.addParams.content) {
|
|
||||||
this.html = '<p>模拟 Ajax 异步设置内容 HTML</p>'
|
|
||||||
}
|
|
||||||
}, 1500)
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
this.saveToLocalStorage()
|
|
||||||
|
|
||||||
// 移除事件监听器
|
|
||||||
window.removeEventListener('beforeunload', this.handleBeforeUnload)
|
|
||||||
|
|
||||||
if (this.autoSaveTimer) {
|
|
||||||
clearTimeout(this.autoSaveTimer)
|
|
||||||
}
|
|
||||||
|
|
||||||
const editor = this.editor
|
|
||||||
if (editor == null) return
|
|
||||||
editor.destroy()
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeRouteLeave(to, from, next) {
|
|
||||||
// 确保获取最新的编辑器内容
|
|
||||||
if (this.editor) {
|
|
||||||
this.addParams.content = this.editor.getHtml()
|
|
||||||
}
|
|
||||||
this.saveToLocalStorage()
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
/* 页面整体样式 */
|
|
||||||
.editor-page {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 20px;
|
|
||||||
background: #f8f9fa;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 页面头部样式 */
|
|
||||||
.page-header {
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
padding: 30px;
|
|
||||||
border-radius: 12px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-left {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-section {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-icon {
|
|
||||||
font-size: 28px;
|
|
||||||
margin-right: 12px;
|
|
||||||
color: #ffd700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0;
|
|
||||||
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-description {
|
|
||||||
font-size: 16px;
|
|
||||||
opacity: 0.9;
|
|
||||||
margin: 0;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 12px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions .el-button {
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 12px 20px;
|
|
||||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions .el-button:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 6px 20px rgba(0,0,0,0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 配置区域样式 */
|
|
||||||
.config-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
|
||||||
border: 1px solid #e9ecef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
border-bottom: 2px solid #f8f9fa;
|
|
||||||
color: #2c3e50;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header i {
|
|
||||||
margin-right: 10px;
|
|
||||||
color: #667eea;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-item label {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #495057;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.required::after {
|
|
||||||
content: '*';
|
|
||||||
color: #e74c3c;
|
|
||||||
margin-left: 4px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 编辑器区域样式 */
|
|
||||||
.editor-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 24px;
|
|
||||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
|
||||||
border: 1px solid #e9ecef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-container {
|
|
||||||
border: 1px solid #dcdfe6;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
background: white;
|
|
||||||
min-height: 650px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 设置编辑器高度 */
|
|
||||||
.editor-container .w-e-text-container {
|
|
||||||
height: 600px !important;
|
|
||||||
min-height: 600px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 编辑器内容区域样式 */
|
|
||||||
.editor-container .w-e-text {
|
|
||||||
height: 600px !important;
|
|
||||||
min-height: 600px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 保存状态样式 */
|
|
||||||
.save-status {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 20px;
|
|
||||||
right: 20px;
|
|
||||||
background: #67c23a;
|
|
||||||
color: white;
|
|
||||||
padding: 12px 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
z-index: 1000;
|
|
||||||
animation: slideIn 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideIn {
|
|
||||||
from {
|
|
||||||
transform: translateX(100%);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: translateX(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 预览对话框样式 */
|
|
||||||
.preview-dialog .el-dialog__body {
|
|
||||||
padding: 20px;
|
|
||||||
max-height: 70vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__header {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__header .el-dialog__title {
|
|
||||||
color: #333;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer {
|
|
||||||
background-color: #f8f9fa;
|
|
||||||
border-top: 1px solid #ebeef5;
|
|
||||||
padding: 15px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer .dialog-footer {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer .dialog-footer .el-button {
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 8px 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer .dialog-footer .el-button:first-child {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer .dialog-footer .el-button:last-child {
|
|
||||||
background-color: #667eea;
|
|
||||||
border-color: #667eea;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-dialog .el-dialog__footer .dialog-footer .el-button:last-child:hover {
|
|
||||||
background-color: #5a67d8;
|
|
||||||
border-color: #5a67d8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 预览内容样式 - 简化版本 */
|
|
||||||
.preview-content {
|
|
||||||
background: white;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-empty {
|
|
||||||
text-align: center;
|
|
||||||
padding: 50px 20px;
|
|
||||||
color: #95a5a6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-empty i {
|
|
||||||
font-size: 48px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-empty p {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.editor-page {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-row {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-status {
|
|
||||||
bottom: 10px;
|
|
||||||
right: 10px;
|
|
||||||
left: 10px;
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Element UI 组件样式优化 */
|
|
||||||
.el-input, .el-select {
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__inner, .el-select .el-input__inner {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #dcdfe6;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__inner:focus, .el-select .el-input__inner:focus {
|
|
||||||
border-color: #667eea;
|
|
||||||
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tag {
|
|
||||||
border-radius: 6px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
import { documentsList } from '../../api/documentManagement'
|
|
||||||
|
|
||||||
export default{
|
|
||||||
name: 'HelpCenter',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
/** 搜索查询字符串 */
|
|
||||||
searchQuery: '',
|
|
||||||
/** 选中的语言 */
|
|
||||||
selectedLanguage: 'zh',
|
|
||||||
/** 分类按钮数据 */
|
|
||||||
categories: [
|
|
||||||
{ id: 1, name: 'home.APIfile', route: 'apiFile' },//API文档
|
|
||||||
{ id: 2, name: 'home.miningTutorial', route: 'AccessMiningPool/nexaAccess' },//挖矿教程
|
|
||||||
{ id: 3, name: 'home.serviceTerms', route: 'ServiceTerms' },//服务条款
|
|
||||||
{ id: 4, name: 'home.rate', route: 'rate' },//费率
|
|
||||||
{ id: 5, name: 'home.announcements', route: 'announcements' },//公告中心
|
|
||||||
{ id: 6, name: 'home.commonProblem', route: 'commonProblem' },//常见问题
|
|
||||||
|
|
||||||
],
|
|
||||||
/** 推荐内容数据 */
|
|
||||||
recommendedItems: [
|
|
||||||
{ id: 1, description: 'home.allocationExplanation' ,route:"allocationExplanation"},//矿池分配及转账规则
|
|
||||||
// { id: 2, description: '余额不足如何任何偿还,该如何规划运营?' },
|
|
||||||
// { id: 3, description: '矿池选择它已经拥有综合的优势时间,怎么办?' }
|
|
||||||
],
|
|
||||||
/** 活动数据 */
|
|
||||||
activities: [
|
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// type: '最新公告',
|
|
||||||
// title: 'LKY将停减税',
|
|
||||||
// author: '文章ID1星期 主发布',
|
|
||||||
// comments: '0'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 2,
|
|
||||||
// type: '最新公告',
|
|
||||||
// title: 'PFP将停减税',
|
|
||||||
// author: '文章ID1星期 11发布',
|
|
||||||
// comments: '0'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 3,
|
|
||||||
// type: '最新公告',
|
|
||||||
// title: 'ETC+ZIL停研发综合日获得',
|
|
||||||
// author: '文章ID1星期 15发布',
|
|
||||||
// comments: '0'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 4,
|
|
||||||
// type: '最新公告',
|
|
||||||
// title: '预计2023年06月19日SCC收益分配说明',
|
|
||||||
// author: '文章ID1星期 18发布',
|
|
||||||
// comments: '0'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: 5,
|
|
||||||
// type: '其他',
|
|
||||||
// title: '关于临时(信为网站、备案管理、矿池编码)',
|
|
||||||
// author: '文章ID1星期 19发布',
|
|
||||||
// comments: '0'
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
activeParams:{
|
|
||||||
type:"3",//公告中心
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:10
|
|
||||||
},
|
|
||||||
TypeList:[
|
|
||||||
{//挖矿教程
|
|
||||||
value:"1",
|
|
||||||
label:"backendSystem.miningTutorial",
|
|
||||||
articleUrl:"AccessMiningPool"
|
|
||||||
},
|
|
||||||
{//常见问题
|
|
||||||
value:"2",
|
|
||||||
label:"backendSystem.commonProblems",
|
|
||||||
articleUrl:"commonProblem"
|
|
||||||
},
|
|
||||||
{//公告中心
|
|
||||||
value:"3",
|
|
||||||
label:"backendSystem.announcementCenter",
|
|
||||||
articleUrl:"announcements"
|
|
||||||
},
|
|
||||||
{//其他
|
|
||||||
value:"0",
|
|
||||||
label:"backendSystem.other",
|
|
||||||
articleUrl:"",
|
|
||||||
children:[{
|
|
||||||
value:"1",
|
|
||||||
label:"home.serviceTerms",
|
|
||||||
articleUrl:"serviceTerms"
|
|
||||||
},{
|
|
||||||
value:"2",
|
|
||||||
label:"home.rate",
|
|
||||||
articleUrl:"rate"
|
|
||||||
},{
|
|
||||||
value:"3",
|
|
||||||
label:"home.APIfile",
|
|
||||||
articleUrl:"apiFile"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
this.$addStorageEvent(1, "TypeList", JSON.stringify(this.TypeList));
|
|
||||||
|
|
||||||
this.fetchActivityList(this.activeParams)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchActivityList(params){
|
|
||||||
const res = await documentsList(params)
|
|
||||||
console.log(res,"res");
|
|
||||||
|
|
||||||
if (res.code === 200) {
|
|
||||||
this.activities = res.rows
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理搜索功能
|
|
||||||
*/
|
|
||||||
handleSearch() {
|
|
||||||
if (this.searchQuery.trim()) {
|
|
||||||
let url = `/${this.$i18n.locale}/searchResult`
|
|
||||||
this.$router.push({
|
|
||||||
path:url,
|
|
||||||
query:{
|
|
||||||
keyword:this.searchQuery
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理分类按钮点击
|
|
||||||
* @param {Object} category - 分类对象
|
|
||||||
*/
|
|
||||||
handleCategoryClick(category) {
|
|
||||||
console.log(category,"i肯定看到");
|
|
||||||
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/${category.route}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理查看更多按钮点击 跳转公告中心页面
|
|
||||||
*/
|
|
||||||
handleViewMore() {
|
|
||||||
this.$router.push(`/${this.$i18n.locale}/announcements`);
|
|
||||||
},
|
|
||||||
handelType(type){
|
|
||||||
try {
|
|
||||||
let label = this.TypeList.find(item => item.value == type).label
|
|
||||||
return this.$t(label)
|
|
||||||
} catch (error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelTime(time){
|
|
||||||
|
|
||||||
try {
|
|
||||||
return `${time.split("T")[0]} ${time.split("T")[1]}`
|
|
||||||
} catch (error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
handleActivityClick(activity){
|
|
||||||
|
|
||||||
let url = `/${this.$i18n.locale}/announcementDetails`
|
|
||||||
// 跳转到公告详情页
|
|
||||||
this.$router.push({
|
|
||||||
path:url,
|
|
||||||
query:{
|
|
||||||
id:activity.id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,388 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="help-center">
|
|
||||||
<!-- 顶部蓝色渐变背景区域 -->
|
|
||||||
<div class="top-section">
|
|
||||||
<!-- <div class="filter-icon">
|
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M3 7H21L15 13V19L9 15V13L3 7Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- 搜索框 -->
|
|
||||||
<div class="search-container">
|
|
||||||
<input
|
|
||||||
v-model="searchQuery"
|
|
||||||
type="text"
|
|
||||||
:placeholder="$t('backendSystem.search') || '搜索'"
|
|
||||||
class="search-input"
|
|
||||||
@keyup.enter="handleSearch"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 主要内容区域 -->
|
|
||||||
<div class="main-content">
|
|
||||||
<!-- 分类按钮网格 -->
|
|
||||||
<div class="category-grid">
|
|
||||||
<button
|
|
||||||
v-for="category in categories"
|
|
||||||
:key="category.id"
|
|
||||||
class="category-btn"
|
|
||||||
@click="handleCategoryClick(category)"
|
|
||||||
@keydown.enter="handleCategoryClick(category)"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
{{ $t(category.name )}}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 推荐内容区域 -->
|
|
||||||
<div class="recommended-section">
|
|
||||||
<h3 class="section-title">{{ $t('backendSystem.recommendContent') || '推荐的内容' }}</h3>
|
|
||||||
<div class="recommended-items">
|
|
||||||
<div
|
|
||||||
v-for="item in recommendedItems"
|
|
||||||
:key="item.id"
|
|
||||||
class="recommended-item"
|
|
||||||
@click="handleCategoryClick(item)"
|
|
||||||
>
|
|
||||||
<p class="item-description" >{{ $t(item.description) }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 最近活动区域 -->
|
|
||||||
<div class="recent-activities">
|
|
||||||
<h3 class="section-title">{{ $t('backendSystem.recentActivities') || '最近活动' }}</h3>
|
|
||||||
<div class="activities-list">
|
|
||||||
<div
|
|
||||||
v-for="activity in activities"
|
|
||||||
:key="activity.id"
|
|
||||||
class="activity-item"
|
|
||||||
@click="handleActivityClick(activity)"
|
|
||||||
>
|
|
||||||
<div class="activity-header">
|
|
||||||
<span class="activity-badge">{{ handelType(activity.type) }}</span>
|
|
||||||
</div>
|
|
||||||
<p class="activity-title">{{ activity.title }}</p>
|
|
||||||
<div class="activity-meta">
|
|
||||||
<span class="activity-author">{{handelTime(activity.createTime) }}</span>
|
|
||||||
<!-- <span class="activity-comments">{{ activity.comments }}</span> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 查看更多链接 -->
|
|
||||||
<div class="view-more">
|
|
||||||
<a href="#" class="view-more-link" @click="handleViewMore">
|
|
||||||
{{ $t('backendSystem.viewMore') || '查看更多活动公告' }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 底部帮助中心链接 -->
|
|
||||||
<!-- <div class="bottom-section">
|
|
||||||
<div class="help-center-link">
|
|
||||||
<span>帮助中心</span>
|
|
||||||
<select v-model="selectedLanguage" class="language-select">
|
|
||||||
<option value="zh">简体中文</option>
|
|
||||||
<option value="en">English</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
/**
|
|
||||||
* 帮助中心/知识库页面组件
|
|
||||||
* 提供搜索、分类浏览、推荐内容和最近活动功能
|
|
||||||
*/
|
|
||||||
import Index from './index.js'
|
|
||||||
export default {
|
|
||||||
mixins:[Index],
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
/**
|
|
||||||
* 帮助中心页面样式
|
|
||||||
*/
|
|
||||||
.help-center {
|
|
||||||
min-height: 100vh;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 顶部蓝色渐变背景区域 */
|
|
||||||
.top-section {
|
|
||||||
position: relative;
|
|
||||||
height: 200px;
|
|
||||||
background: linear-gradient(135deg, #5721E4 0%, #5721E4 50%, #F4BDD1 100%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 过滤器图标 */
|
|
||||||
.filter-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px;
|
|
||||||
right: 20px;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
transition: background 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-icon:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 搜索框容器 */
|
|
||||||
.search-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 搜索输入框 */
|
|
||||||
.search-input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 20px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 25px;
|
|
||||||
background: rgba(255, 255, 255, 0.9);
|
|
||||||
font-size: 16px;
|
|
||||||
outline: none;
|
|
||||||
transition: background 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-input:focus {
|
|
||||||
background: rgba(255, 255, 255, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-input::placeholder {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 主要内容区域 */
|
|
||||||
.main-content {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 40px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 分类按钮网格 */
|
|
||||||
.category-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 分类按钮 */
|
|
||||||
.category-btn {
|
|
||||||
padding: 20px;
|
|
||||||
border: 2px solid #e0e0e0;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: white;
|
|
||||||
color: #333;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
text-align: center;
|
|
||||||
min-height: 60px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-btn:hover {
|
|
||||||
border-color: #5721E4;
|
|
||||||
background: #f8f9ff;
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(42, 82, 152, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-btn:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: #2a5298;
|
|
||||||
box-shadow: 0 0 0 3px rgba(42, 82, 152, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 章节标题 */
|
|
||||||
.section-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 推荐内容区域 */
|
|
||||||
.recommended-section {
|
|
||||||
margin-bottom: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recommended-items {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.recommended-item {
|
|
||||||
background: white;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recommended-item:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-description {
|
|
||||||
color: #666;
|
|
||||||
line-height: 1.6;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 最近活动区域 */
|
|
||||||
.recent-activities {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activities-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-item {
|
|
||||||
background: white;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-item:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-header {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 4px 12px;
|
|
||||||
background: #e3f2fd;
|
|
||||||
color: #1976d2;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-meta {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-comments {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 查看更多链接 */
|
|
||||||
.view-more {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-more-link {
|
|
||||||
color: #2a5298;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-more-link:hover {
|
|
||||||
color: #1e3c72;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 底部区域 */
|
|
||||||
.bottom-section {
|
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 20px;
|
|
||||||
border-top: 1px solid #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-center-link {
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.language-select {
|
|
||||||
padding: 5px 10px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: white;
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.category-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recommended-items {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
padding: 20px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-container {
|
|
||||||
max-width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-center-link {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activity-meta {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import { watch } from "vue";
|
import { watch } from "vue";
|
||||||
import { getCoinInfo, getPoolPower, getMinerCount, getLuck, getBlockInfo, getNetPower, getParam } from "../../api/home"
|
import { getCoinInfo, getPoolPower, getMinerCount, getLuck, getBlockInfo, getNetPower, getParam } from "../../api/home"
|
||||||
import { listBroadcast,getBroadcast} from "../../api/broadcast"
|
|
||||||
import { line } from "../../utils/echarts";
|
import { line } from "../../utils/echarts";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import { Debounce, throttle } from "../../utils/publicMethods";
|
import { Debounce, throttle } from "../../utils/publicMethods";
|
||||||
@@ -76,11 +76,11 @@ export default {
|
|||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
|
|
||||||
padding: [0, 0, 0, -40],
|
padding: [0, 0, 0, -40],
|
||||||
},
|
}
|
||||||
// min: `dataMin`,
|
// min: `dataMin`,
|
||||||
// max: `dataMax`,
|
// max: `dataMax`,
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
formatter: function (value) {
|
// formatter: function (value) {
|
||||||
// let data
|
// let data
|
||||||
// if (value > 10000000) {
|
// if (value > 10000000) {
|
||||||
// data = `${(value / 10000000)} KW`
|
// data = `${(value / 10000000)} KW`
|
||||||
@@ -89,9 +89,9 @@ export default {
|
|||||||
// } else if (value / 10000) {
|
// } else if (value / 10000) {
|
||||||
// data = `${(value / 10000)} W`
|
// data = `${(value / 10000)} W`
|
||||||
// }
|
// }
|
||||||
return value
|
// return data
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -276,9 +276,9 @@ export default {
|
|||||||
name: "GH/s",
|
name: "GH/s",
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
padding: [0, 0, 0, -40],
|
padding: [0, 0, 0, -40],
|
||||||
},
|
}
|
||||||
axisLabel: {
|
// axisLabel: {
|
||||||
formatter: function (value) {
|
// formatter: function (value) {
|
||||||
// let data
|
// let data
|
||||||
// if (value > 10000000) {
|
// if (value > 10000000) {
|
||||||
// data = `${(value / 10000000)} KW`
|
// data = `${(value / 10000000)} KW`
|
||||||
@@ -287,9 +287,9 @@ export default {
|
|||||||
// } else if (value / 10000) {
|
// } else if (value / 10000) {
|
||||||
// data = `${(value / 10000)} W`
|
// data = `${(value / 10000)} W`
|
||||||
// }
|
// }
|
||||||
return value
|
// return data
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
position: "right",
|
position: "right",
|
||||||
@@ -485,17 +485,17 @@ export default {
|
|||||||
amount: 100,
|
amount: 100,
|
||||||
|
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// path: "enxAccess",
|
path: "enxAccess",
|
||||||
// value: "enx",
|
value: "enx",
|
||||||
// label: "Entropyx(enx)",
|
label: "Entropyx(enx)",
|
||||||
// img: require("../../assets/img/currency/enx.svg"),
|
img: require("../../assets/img/currency/enx.svg"),
|
||||||
// imgUrl: `${this.$baseApi}img/enx.svg`,
|
imgUrl: `${this.$baseApi}img/enx.svg`,
|
||||||
// name: "course.ENXcourse",
|
name: "course.ENXcourse",
|
||||||
// show: true,
|
show: true,
|
||||||
// amount: 5000,
|
amount: 5000,
|
||||||
|
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
path: "alphminingPool",
|
path: "alphminingPool",
|
||||||
value: "alph",
|
value: "alph",
|
||||||
@@ -506,30 +506,7 @@ export default {
|
|||||||
show: true,
|
show: true,
|
||||||
amount: 1,
|
amount: 1,
|
||||||
|
|
||||||
},
|
}
|
||||||
{
|
|
||||||
path: "xmr",
|
|
||||||
value: "monero",
|
|
||||||
label: "xmr",
|
|
||||||
img: require("../../assets/img/currency/xmr.png"),
|
|
||||||
imgUrl: `${this.$baseApi}img/xmr.png`,
|
|
||||||
name: "course.xmrCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 0.1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "xtm",
|
|
||||||
value: "sha3x",
|
|
||||||
label: "xtm(sha3x)",
|
|
||||||
img: require("../../assets/img/currency/xtm.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/xtm.svg`,
|
|
||||||
name: "course.xmrCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 10000,
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// { //告知已删除此币种 Radiant
|
// { //告知已删除此币种 Radiant
|
||||||
// value: "dgb2_odo",
|
// value: "dgb2_odo",
|
||||||
// label: "dgb-odocrypt-pool2",
|
// label: "dgb-odocrypt-pool2",
|
||||||
@@ -790,40 +767,13 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
isInternalChange: false,
|
isInternalChange: false,
|
||||||
broadcastList: [
|
|
||||||
{ id: `b1`, content: this.$t(`home.describe`),buttonContent:[this.$t(`home.view`)],buttonPath:["/allocationExplanation"] },
|
|
||||||
// { id: `b2`, content: `广播内容2测试` },
|
|
||||||
// { id: `b3`, content: `广播内容3测试` },
|
|
||||||
// { id: `b4`, content: `广播内容4测试` },
|
|
||||||
|
|
||||||
],
|
|
||||||
currentBroadcastIndex: 0,
|
|
||||||
scrollTimer: null,
|
|
||||||
delayScrollTimer: null, // 移动端延迟滚动定时器
|
|
||||||
isTransition: true,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
// 末尾加一条"克隆的第一条"用于无缝滚动
|
|
||||||
broadcastListForLoop() {
|
|
||||||
if (this.broadcastList.length === 0) return [];
|
|
||||||
if (this.broadcastList.length === 1) return this.broadcastList;
|
|
||||||
return [...this.broadcastList, this.broadcastList[0]];
|
|
||||||
},
|
|
||||||
scrollStyle() {
|
|
||||||
return {
|
|
||||||
transform: `translateY(-${this.currentBroadcastIndex * 30}px)`,
|
|
||||||
transition: this.isTransition ? 'transform 0.5s cubic-bezier(.4,0,.2,1)' : 'none',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
// 移动端专用滚动样式
|
|
||||||
mobileScrollStyle() {
|
|
||||||
return {
|
|
||||||
transform: `translateY(-${this.currentBroadcastIndex * 40}px)`, // 移动端使用更大的行高
|
|
||||||
transition: this.isTransition ? 'transform 0.5s cubic-bezier(.4,0,.2,1)' : 'none',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
"$i18n.locale": (val) => {
|
"$i18n.locale": (val) => {
|
||||||
location.reload();//刷新页面 刷新echarts
|
location.reload();//刷新页面 刷新echarts
|
||||||
@@ -841,6 +791,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.lang = this.$i18n.locale; // 初始化语言值
|
this.lang = this.$i18n.locale; // 初始化语言值
|
||||||
this.$addStorageEvent(1, `activeItemCoin`, JSON.stringify(this.currencyList[0]))
|
this.$addStorageEvent(1, `activeItemCoin`, JSON.stringify(this.currencyList[0]))
|
||||||
this.minerChartLoading = true
|
this.minerChartLoading = true
|
||||||
@@ -872,70 +825,16 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}else{ //动态计算图表的grid.left 让左侧的Y轴标签显示完全
|
|
||||||
|
|
||||||
|
|
||||||
const yAxis = this.option.yAxis[0]; // 第一个 Y 轴
|
|
||||||
const maxValue = Math.max(...this.option.series[0].data); // 获取数据最大值
|
|
||||||
const formatter = yAxis.axisLabel.formatter;
|
|
||||||
const formattedValue = formatter(maxValue); // 格式化最大值
|
|
||||||
|
|
||||||
|
|
||||||
// 创建一个临时 DOM 元素计算宽度
|
|
||||||
const tempDiv = document.createElement('div');
|
|
||||||
tempDiv.style.position = 'absolute';
|
|
||||||
tempDiv.style.visibility = 'hidden';
|
|
||||||
tempDiv.style.fontSize = '12px'; // 与 axisLabel.fontSize 一致
|
|
||||||
tempDiv.innerText = formattedValue;
|
|
||||||
document.body.appendChild(tempDiv);
|
|
||||||
const labelWidth = tempDiv.offsetWidth;
|
|
||||||
document.body.removeChild(tempDiv);
|
|
||||||
|
|
||||||
// 动态设置 grid.left,加上安全边距
|
|
||||||
const safeMargin = 20;
|
|
||||||
this.option.grid.left = labelWidth + safeMargin + 'px';
|
|
||||||
|
|
||||||
|
|
||||||
// ------------全网算力图---------------
|
|
||||||
//
|
|
||||||
|
|
||||||
const yAxis2 = this.minerOption.yAxis[0]; // 第一个 Y 轴
|
|
||||||
const maxValue2 = Math.max(...this.minerOption.series[0].data); // 获取数据最大值
|
|
||||||
const formatter2 = yAxis2.axisLabel.formatter;
|
|
||||||
const formattedValue2 = formatter2(maxValue2); // 格式化最大值
|
|
||||||
|
|
||||||
|
|
||||||
// 创建一个临时 DOM 元素计算宽度
|
|
||||||
const tempDiv2 = document.createElement('div');
|
|
||||||
tempDiv2.style.position = 'absolute';
|
|
||||||
tempDiv2.style.visibility = 'hidden';
|
|
||||||
tempDiv2.style.fontSize = '12px'; // 与 axisLabel.fontSize 一致
|
|
||||||
tempDiv2.innerText = formattedValue2;
|
|
||||||
document.body.appendChild(tempDiv2);
|
|
||||||
const labelWidth2 = tempDiv2.offsetWidth;
|
|
||||||
document.body.removeChild(tempDiv2);
|
|
||||||
// 动态设置 grid.left,加上安全边距
|
|
||||||
const safeMargin2 = 20;
|
|
||||||
this.minerOption.grid.left = labelWidth2 + safeMargin2 + 'px';
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.getBlockInfoData(this.BlockInfoParams)
|
this.getBlockInfoData(this.BlockInfoParams)
|
||||||
this.getCoinInfoData(this.params)
|
this.getCoinInfoData(this.params)
|
||||||
this.getPoolPowerData(this.PowerParams)
|
this.getPoolPowerData(this.PowerParams)
|
||||||
|
|
||||||
// 注册需要在网络恢复后自动重新调用的方法
|
|
||||||
this.registerRecoveryMethod('getCoinInfoData', this.params);
|
|
||||||
this.registerRecoveryMethod('getPoolPowerData', this.PowerParams);
|
|
||||||
this.registerRecoveryMethod('getBlockInfoData', this.BlockInfoParams);
|
|
||||||
|
|
||||||
this.$addStorageEvent(1, `currencyList`, JSON.stringify(this.currencyList))
|
this.$addStorageEvent(1, `currencyList`, JSON.stringify(this.currencyList))
|
||||||
if (this.$refs.select) {
|
if (this.$refs.select) {
|
||||||
this.$refs.select.$el.children[0].children[0].setAttribute('style', `background:url(${this.$baseApi}/img/nexa.png) no-repeat 10PX;background-size: 20PX 20PX;color:#333;padding-left: 30PX;`);
|
this.$refs.select.$el.children[0].children[0].setAttribute('style', "background:url(https://test.m2pool.com/img/nexa.png) no-repeat 10PX;background-size: 20PX 20PX;color:#333;padding-left: 30PX;");
|
||||||
|
|
||||||
}
|
}
|
||||||
this.fetchParam({ coin: this.params.coin })
|
this.fetchParam({ coin: this.params.coin })
|
||||||
@@ -949,122 +848,11 @@ export default {
|
|||||||
this.activeItemCoin=JSON.parse(value)
|
this.activeItemCoin=JSON.parse(value)
|
||||||
|
|
||||||
});
|
});
|
||||||
// this.getBroadcastList({pageNum:1,pageSize:100})
|
|
||||||
|
|
||||||
this.getBroadcastList({lang:this.$i18n.locale})
|
|
||||||
this.startScroll();
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
|
|
||||||
this.startScroll();
|
|
||||||
});
|
|
||||||
window.addEventListener('resize', this.setItemHeight);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
|
||||||
* 处理广播项点击事件
|
|
||||||
*/
|
|
||||||
handleCustomClick(item) {
|
|
||||||
console.log('广播项被点击:', item);
|
|
||||||
this.$message.info(`广播: ${item.content}`);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理广播错误
|
|
||||||
*/
|
|
||||||
handleBroadcastError(error) {
|
|
||||||
console.error('广播组件错误:', error);
|
|
||||||
},
|
|
||||||
//获取广播列表
|
|
||||||
async getBroadcastList(params){
|
|
||||||
// const data = await listBroadcast(params)
|
|
||||||
const data = await getBroadcast(params)
|
|
||||||
|
|
||||||
if (data && data.code == 200) {
|
|
||||||
|
|
||||||
let broadcastList = data.data
|
|
||||||
|
|
||||||
// 处理接口返回的数据,将字符串格式的buttonContent和buttonPath转换为数组
|
|
||||||
broadcastList = broadcastList.map(item => {
|
|
||||||
// 处理 buttonContent
|
|
||||||
if (item.buttonContent) {
|
|
||||||
if (typeof item.buttonContent === 'string') {
|
|
||||||
// 将逗号分隔的字符串转换为数组,兼容中英文逗号
|
|
||||||
item.buttonContent = item.buttonContent.split(/[,,]/).map(btn => btn.trim()).filter(btn => btn);
|
|
||||||
} else if (!Array.isArray(item.buttonContent)) {
|
|
||||||
// 如果不是字符串也不是数组,转为空数组
|
|
||||||
item.buttonContent = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果 buttonContent 不存在,设为空数组
|
|
||||||
item.buttonContent = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 buttonPath
|
|
||||||
if (item.buttonPath) {
|
|
||||||
if (typeof item.buttonPath === 'string') {
|
|
||||||
// 将逗号分隔的字符串转换为数组,兼容中英文逗号
|
|
||||||
item.buttonPath = item.buttonPath.split(/[,,]/).map(path => path.trim()).filter(path => path);
|
|
||||||
} else if (!Array.isArray(item.buttonPath)) {
|
|
||||||
// 如果不是字符串也不是数组,转为空数组
|
|
||||||
item.buttonPath = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果 buttonPath 不存在,设为空数组
|
|
||||||
item.buttonPath = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保 buttonContent 和 buttonPath 长度一致
|
|
||||||
if (item.buttonContent.length !== item.buttonPath.length) {
|
|
||||||
const minLength = Math.min(item.buttonContent.length, item.buttonPath.length);
|
|
||||||
item.buttonContent = item.buttonContent.slice(0, minLength);
|
|
||||||
item.buttonPath = item.buttonPath.slice(0, minLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.broadcastList =[...this.broadcastList,...broadcastList]
|
|
||||||
|
|
||||||
console.log(this.broadcastList,'this.broadcastList');
|
|
||||||
|
|
||||||
this.currentBroadcastIndex = 0; // 新数据时重置索引
|
|
||||||
if(this.broadcastList.length > 1){
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.startScroll();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
handelOptionYAxis(option){
|
|
||||||
const yAxis = option.yAxis[0]; // 第一个 Y 轴
|
|
||||||
const maxValue = Math.max(...option.series[0].data); // 获取数据最大值
|
|
||||||
const formatter = yAxis.axisLabel.formatter;
|
|
||||||
const formattedValue = formatter(maxValue); // 格式化最大值
|
|
||||||
|
|
||||||
|
|
||||||
// 创建一个临时 DOM 元素计算宽度
|
|
||||||
const tempDiv = document.createElement('div');
|
|
||||||
tempDiv.style.position = 'absolute';
|
|
||||||
tempDiv.style.visibility = 'hidden';
|
|
||||||
tempDiv.style.fontSize = '12px'; // 与 axisLabel.fontSize 一致
|
|
||||||
tempDiv.innerText = formattedValue;
|
|
||||||
document.body.appendChild(tempDiv);
|
|
||||||
const labelWidth = tempDiv.offsetWidth;
|
|
||||||
document.body.removeChild(tempDiv);
|
|
||||||
|
|
||||||
// 动态设置 grid.left,加上安全边距
|
|
||||||
const safeMargin = 20;
|
|
||||||
option.grid.left = labelWidth + safeMargin + 'px';
|
|
||||||
|
|
||||||
return option
|
|
||||||
},
|
|
||||||
slideLeft() {
|
slideLeft() {
|
||||||
const allLength = this.currencyList.length * 120
|
const allLength = this.currencyList.length * 120
|
||||||
const boxLength = document.getElementById('list-box').clientWidth
|
const boxLength = document.getElementById('list-box').clientWidth
|
||||||
@@ -1117,7 +905,7 @@ export default {
|
|||||||
this.MinerChart = echarts.init(document.getElementById("minerChart"));
|
this.MinerChart = echarts.init(document.getElementById("minerChart"));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.minerOption= this.handelOptionYAxis(this.minerOption) // Y轴文字显示动态调整grid.left
|
|
||||||
this.minerOption.series[0].name = this.$t(`home.networkPower`)
|
this.minerOption.series[0].name = this.$t(`home.networkPower`)
|
||||||
this.minerOption.series[1].name = this.$t(`home.currencyPrice`)
|
this.minerOption.series[1].name = this.$t(`home.currencyPrice`)
|
||||||
this.MinerChart.setOption(this.minerOption);
|
this.MinerChart.setOption(this.minerOption);
|
||||||
@@ -1185,7 +973,61 @@ export default {
|
|||||||
|
|
||||||
}, 200),
|
}, 200),
|
||||||
|
|
||||||
|
// async getPoolPowerData(params) {
|
||||||
|
// this.minerChartLoading = true
|
||||||
|
// const data = await getPoolPower(params)
|
||||||
|
// if (!data) {
|
||||||
|
// this.minerChartLoading = false
|
||||||
|
// if (this.myChart) {
|
||||||
|
// this.myChart.dispose()//销毁图表实列
|
||||||
|
// }
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// let chartData = data.data
|
||||||
|
// let xData = []
|
||||||
|
// let pvData = []
|
||||||
|
// let rejectRate = []
|
||||||
|
// let price = []
|
||||||
|
// chartData.forEach(item => {
|
||||||
|
|
||||||
|
// if (item.date.includes(`T`) && params.interval == `rt`) {
|
||||||
|
|
||||||
|
// item.date = `${item.date.split("T")[0]} ${item.date.split("T")[1].split(`.`)[0]}`
|
||||||
|
// } else if (item.date.includes(`T`) && params.interval == `1d`) {
|
||||||
|
// item.date = item.date.split("T")[0]
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// xData.push(item.date)
|
||||||
|
// pvData.push(Number(item.pv).toFixed(2))
|
||||||
|
// // rejectRate.push((item.rejectRate * 100).toFixed(2))
|
||||||
|
// if (item.price == 0) {
|
||||||
|
// price.push(item.price)
|
||||||
|
// } else if (item.price < 1) {
|
||||||
|
// price.push(Number(item.price).toFixed(8))
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// price.push(Number(item.price).toFixed(2))
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// });
|
||||||
|
// // this.maxValue = Math.max(...rejectRate);
|
||||||
|
// // let leftYMaxData = Math.max(...pvData);
|
||||||
|
// // this.option.yAxis[0].max =leftYMaxData*2
|
||||||
|
// this.option.xAxis.data = xData
|
||||||
|
// this.option.series[0].data = pvData
|
||||||
|
// // this.option.series[1].data = rejectRate
|
||||||
|
// this.option.series[1].data = price
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.inCharts()
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// },
|
||||||
getPoolPowerData: Debounce(async function (params) {
|
getPoolPowerData: Debounce(async function (params) {
|
||||||
// this.minerChartLoading = true
|
// this.minerChartLoading = true
|
||||||
this.setLoading('minerChartLoading', true);
|
this.setLoading('minerChartLoading', true);
|
||||||
@@ -1233,8 +1075,6 @@ export default {
|
|||||||
// let leftYMaxData = Math.max(...pvData);
|
// let leftYMaxData = Math.max(...pvData);
|
||||||
// this.option.yAxis[0].max =leftYMaxData*2
|
// this.option.yAxis[0].max =leftYMaxData*2
|
||||||
this.option.xAxis.data = xData
|
this.option.xAxis.data = xData
|
||||||
|
|
||||||
this.option.yAxis[0].name = chartData[0].unit
|
|
||||||
this.option.series[0].data = pvData
|
this.option.series[0].data = pvData
|
||||||
// this.option.series[1].data = rejectRate
|
// this.option.series[1].data = rejectRate
|
||||||
this.option.series[1].data = price
|
this.option.series[1].data = price
|
||||||
@@ -1294,10 +1134,6 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
this.minerOption.xAxis.data = xData
|
this.minerOption.xAxis.data = xData
|
||||||
if (MinerCount[0] && MinerCount[0].unit) {
|
|
||||||
this.minerOption.yAxis[0].name = MinerCount[0].unit
|
|
||||||
}
|
|
||||||
|
|
||||||
this.minerOption.series[0].data = pvData
|
this.minerOption.series[0].data = pvData
|
||||||
this.minerOption.series[1].data = price
|
this.minerOption.series[1].data = price
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@@ -1385,10 +1221,36 @@ export default {
|
|||||||
|
|
||||||
}, 200),
|
}, 200),
|
||||||
|
|
||||||
|
// async getBlockInfoData(params) {
|
||||||
|
// this.reportBlockLoading = true
|
||||||
|
// const data = await getBlockInfo(params)
|
||||||
|
// if (data && data.code == 200) {
|
||||||
|
// this.BlockShow = true
|
||||||
|
// this.newBlockInfoData = []
|
||||||
|
// this.BlockInfoData = data.rows
|
||||||
|
// if (!this.BlockInfoData[0]) {
|
||||||
|
// this.reportBlockLoading = false
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// this.BlockInfoData.forEach((item, index) => {
|
||||||
|
// item.date = `${item.date.split("T")[0]} ${item.date.split("T")[1].split(`.`)[0]}`
|
||||||
|
// if (index < 8) {
|
||||||
|
// this.newBlockInfoData.push(item)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// this.BlockShow = false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.reportBlockLoading = false
|
||||||
|
// },
|
||||||
|
|
||||||
getBlockInfoData: Debounce(async function (params) {
|
getBlockInfoData: Debounce(async function (params) {
|
||||||
try {
|
|
||||||
// this.reportBlockLoading = true
|
// this.reportBlockLoading = true
|
||||||
this.setLoading('reportBlockLoading', true);
|
this.setLoading('reportBlockLoading', true);
|
||||||
const data = await getBlockInfo(params)
|
const data = await getBlockInfo(params)
|
||||||
@@ -1397,8 +1259,7 @@ export default {
|
|||||||
this.newBlockInfoData = []
|
this.newBlockInfoData = []
|
||||||
this.BlockInfoData = data.rows
|
this.BlockInfoData = data.rows
|
||||||
if (!this.BlockInfoData[0]) {
|
if (!this.BlockInfoData[0]) {
|
||||||
// this.reportBlockLoading = false
|
this.reportBlockLoading = false
|
||||||
this.setLoading('reportBlockLoading', false);
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1410,21 +1271,13 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.BlockShow = false
|
this.BlockShow = false
|
||||||
}
|
}
|
||||||
this.setLoading('reportBlockLoading', false);
|
this.setLoading('reportBlockLoading', false);
|
||||||
// this.reportBlockLoading = false
|
// this.reportBlockLoading = false
|
||||||
} catch (error) {
|
|
||||||
console.error('获取区块信息失败:', error);
|
|
||||||
this.BlockShow = false;
|
|
||||||
}finally {
|
|
||||||
// 确保在任何情况下都会重置 loading 状态
|
|
||||||
this.setLoading('reportBlockLoading', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1468,55 +1321,39 @@ export default {
|
|||||||
|
|
||||||
switch (this.time) {
|
switch (this.time) {
|
||||||
case "day":
|
case "day":
|
||||||
this.profit = result.toFixed(8)
|
// this.profit = result.toFixed(10)
|
||||||
// this.profit = Math.floor(result * 1e10) / 1e10;
|
// this.profit = Math.floor(result * 1e10) / 1e10;
|
||||||
// this.profit = this.toFixedNoRound(result, 10);
|
this.profit = this.toFixedNoRound(result, 10);
|
||||||
break;
|
break;
|
||||||
case "week":
|
case "week":
|
||||||
this.profit = (result * 7).toFixed(8)
|
// this.profit = (result * 7).toFixed(10)
|
||||||
// this.profit = Math.floor(result * 7 * 1e10) / 1e10;
|
// this.profit = Math.floor(result * 7 * 1e10) / 1e10;
|
||||||
// this.profit = this.toFixedNoRound(result * 7, 10);
|
this.profit = this.toFixedNoRound(result * 7, 10);
|
||||||
break;
|
break;
|
||||||
case "month":
|
case "month":
|
||||||
this.profit = (result * 30).toFixed(8)
|
// this.profit = (result * 30).toFixed(10)
|
||||||
// this.profit = Math.floor(result * 30 * 1e10) / 1e10;
|
// this.profit = Math.floor(result * 30 * 1e10) / 1e10;
|
||||||
// this.profit = this.toFixedNoRound(result * 30, 10);
|
this.profit = this.toFixedNoRound(result * 30, 10);
|
||||||
break;
|
break;
|
||||||
case "year":
|
case "year":
|
||||||
this.profit = (result * 365).toFixed(8)
|
// this.profit = (result * 365).toFixed(10)
|
||||||
// this.profit = Math.floor(result * 365 * 1e10) / 1e10;
|
// this.profit = Math.floor(result * 365 * 1e10) / 1e10;
|
||||||
// this.profit = this.toFixedNoRound(result * 365, 10);
|
this.profit = this.toFixedNoRound(result * 365, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const nexaFormatter = new Intl.NumberFormat("en-US", {
|
|
||||||
minimumFractionDigits: 2, // 强制显示 2 位小数(不足补零)
|
// 10000000000000000
|
||||||
maximumFractionDigits: 2, // 可选:限制最多 2 位小数(避免多余位数)
|
|
||||||
useGrouping: true, // 不使用千位分隔符(如 1,000)
|
|
||||||
});
|
|
||||||
if (this.value == "nexa") {
|
|
||||||
this.profit = nexaFormatter.format(this.profit);
|
|
||||||
} else {
|
|
||||||
const formatter = new Intl.NumberFormat("en-US", {
|
const formatter = new Intl.NumberFormat("en-US", {
|
||||||
minimumFractionDigits: 8, // 强制显示足够多的小数位
|
minimumFractionDigits: 10, // 强制显示足够多的小数位
|
||||||
useGrouping: true, // 不使用千位分隔符(如 1,000)
|
useGrouping: true, // 不使用千位分隔符(如 1,000)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.profit = formatter.format(this.profit);
|
this.profit = formatter.format(this.profit);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// const formatter = new Intl.NumberFormat("en-US", {
|
|
||||||
// minimumFractionDigits: 8, // 强制显示足够多的小数位
|
|
||||||
// useGrouping: false, // 不使用千位分隔符(如 1,000)
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
// this.profit = formatter.format(this.profit);
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
toFixedNoRound(value, decimals = 10) {//保留10位小数 不四舍五入
|
toFixedNoRound(value, decimals = 10) {//保留10位小数 不四舍五入
|
||||||
@@ -1548,11 +1385,11 @@ export default {
|
|||||||
handelProfitCalculation() {
|
handelProfitCalculation() {
|
||||||
|
|
||||||
for (const key in this.CalculatorData) {
|
for (const key in this.CalculatorData) {
|
||||||
if (this.CalculatorData[key]!==0 && !this.CalculatorData[key]) {
|
if (!this.CalculatorData[key]) {
|
||||||
this.$message({
|
// this.$message({
|
||||||
message: this.$t(`home.acquisitionFailed`),
|
// message: this.$t(`home.acquisitionFailed`),
|
||||||
type: "error",
|
// type: "error",
|
||||||
});
|
// });
|
||||||
this.profit = 0
|
this.profit = 0
|
||||||
// var myDiv = document.getElementById('myDiv');
|
// var myDiv = document.getElementById('myDiv');
|
||||||
// this.disableElement(myDiv);
|
// this.disableElement(myDiv);
|
||||||
@@ -1568,7 +1405,6 @@ export default {
|
|||||||
this.showCalculator = false
|
this.showCalculator = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
changeSelection(scope) {
|
changeSelection(scope) {
|
||||||
let brand = scope
|
let brand = scope
|
||||||
for (let index in this.currencyList) {
|
for (let index in this.currencyList) {
|
||||||
@@ -1586,13 +1422,12 @@ export default {
|
|||||||
if (url === '/AccessMiningPool') {
|
if (url === '/AccessMiningPool') {
|
||||||
const coin = this.currencyList.find(item => item.value === this.params.coin);
|
const coin = this.currencyList.find(item => item.value === this.params.coin);
|
||||||
if (!coin) return;
|
if (!coin) return;
|
||||||
// let jumpName = coin.path.charAt(0).toUpperCase() + coin.path.slice(1) //name跳转 首字母大写
|
let jumpName = coin.path.charAt(0).toUpperCase() + coin.path.slice(1) //name跳转 首字母大写
|
||||||
|
|
||||||
let url = `/${this.lang}/AccessMiningPool`
|
|
||||||
// 使用 name 进行导航,避免重复的路由参数
|
// 使用 name 进行导航,避免重复的路由参数
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name:'AccessMiningPool',
|
name: jumpName,
|
||||||
params: {
|
params: {
|
||||||
|
lang: this.lang,
|
||||||
coin: this.params.coin,
|
coin: this.params.coin,
|
||||||
imgUrl: this.currencyPath
|
imgUrl: this.currencyPath
|
||||||
|
|
||||||
@@ -1602,56 +1437,14 @@ export default {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 移除开头的斜杠,统一处理路径格式
|
// 移除开头的斜杠,统一处理路径格式
|
||||||
// const cleanPath = url.startsWith('/') ? url.slice(1) : url;
|
const cleanPath = url.startsWith('/') ? url.slice(1) : url;
|
||||||
let cleanPath = `/${this.lang}/AccessMiningPool`
|
this.$router.push(`/${this.lang}/${cleanPath}`);
|
||||||
this.$router.push(cleanPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
|
||||||
handelJumpBroadcast(url){
|
|
||||||
|
|
||||||
if (url === '/AccessMiningPool') {
|
|
||||||
const coin = this.currencyList.find(item => item.value === this.params.coin);
|
|
||||||
if (!coin) return;
|
|
||||||
// let jumpName = coin.path.charAt(0).toUpperCase() + coin.path.slice(1) //name跳转 首字母大写
|
|
||||||
|
|
||||||
let url = `/${this.lang}/AccessMiningPool`
|
|
||||||
// 使用 name 进行导航,避免重复的路由参数
|
|
||||||
this.$router.push({
|
|
||||||
name:'AccessMiningPool',
|
|
||||||
params: {
|
|
||||||
coin: this.params.coin,
|
|
||||||
imgUrl: this.currencyPath
|
|
||||||
|
|
||||||
},
|
|
||||||
replace: false // 保留历史记录,允许回退
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$router.push(`/${this.lang}${url}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
handelCalculation() {
|
handelCalculation() {
|
||||||
this.calculateIncome()
|
this.calculateIncome()
|
||||||
},
|
},
|
||||||
// 获取单个币种项目的完整宽度(包含margin)
|
|
||||||
getItemFullWidth() {
|
|
||||||
const listEl = this.$refs.currencyList;
|
|
||||||
if (!listEl) return 120;
|
|
||||||
|
|
||||||
const firstItem = listEl.querySelector('.list-item');
|
|
||||||
if (!firstItem) return 120;
|
|
||||||
|
|
||||||
const style = window.getComputedStyle(firstItem);
|
|
||||||
const width = firstItem.offsetWidth;
|
|
||||||
const marginLeft = parseInt(style.marginLeft) || 0;
|
|
||||||
const marginRight = parseInt(style.marginRight) || 0;
|
|
||||||
|
|
||||||
return width + marginLeft + marginRight;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 左滑动逻辑
|
// 左滑动逻辑
|
||||||
scrollLeft() {
|
scrollLeft() {
|
||||||
@@ -1681,37 +1474,23 @@ scrollRight() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// clickCurrency: throttle(function(item) {
|
||||||
|
// this.currency = item.label
|
||||||
// // 左滑动逻辑
|
// this.currencyPath = item.imgUrl
|
||||||
// scrollLeft() {
|
// this.params.coin = item.value
|
||||||
// const allLength = this.currencyList.length * 120
|
// this.BlockInfoParams.coin = item.value
|
||||||
// const boxLength = document.getElementById('list-box').clientWidth
|
// this.itemActive = item.value
|
||||||
// if (allLength < boxLength) return
|
// this.PowerParams.coin = item.value
|
||||||
// const listEl = document.getElementById('list')
|
// this.getCoinInfoData(this.params)
|
||||||
// const leftMove = Math.abs(parseInt(window.getComputedStyle(listEl, null)?.left))
|
// this.getBlockInfoData(this.BlockInfoParams)
|
||||||
// if (leftMove + boxLength - 360 < boxLength) {
|
// // this.getPoolPowerData(this.PowerParams)
|
||||||
// // 到最开始的时候
|
// // this.getMinerCountData(this.params)
|
||||||
// listEl.style.left = '0PX'
|
// if (this.powerActive) {
|
||||||
// } else {
|
// this.handelPower()
|
||||||
// listEl.style.left = '-' + (leftMove - 360) + 'PX'
|
// } else if (!this.powerActive) {
|
||||||
|
// this.handelMiner()
|
||||||
// }
|
// }
|
||||||
// },
|
// }, 1000),
|
||||||
// // 右滑动逻辑
|
|
||||||
// scrollRight() {
|
|
||||||
// const allLength = this.currencyList.length * 120
|
|
||||||
// const boxLength = document.getElementById('list-box').clientWidth
|
|
||||||
// if (allLength < boxLength) return
|
|
||||||
// const listEl = document.getElementById('list')
|
|
||||||
// const leftMove = Math.abs(parseInt(window.getComputedStyle(listEl, null)?.left))
|
|
||||||
// if (leftMove + boxLength + 360 > allLength) {
|
|
||||||
// listEl.style.left = '-' + (allLength - boxLength) + 'PX'
|
|
||||||
// } else {
|
|
||||||
// listEl.style.left = '-' + (leftMove + 360) + 'PX'
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
|
|
||||||
handleActiveItemChange(item) {
|
handleActiveItemChange(item) {
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
@@ -1851,39 +1630,10 @@ scrollRight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
startScroll() {
|
|
||||||
if (this.scrollTimer) clearInterval(this.scrollTimer);
|
|
||||||
// 只有多于1条才滚动
|
|
||||||
if (this.broadcastList.length <= 1) return;
|
|
||||||
this.scrollTimer = setInterval(this.nextScroll, 3000);
|
|
||||||
},
|
|
||||||
stopScroll() {
|
|
||||||
if (this.scrollTimer) clearInterval(this.scrollTimer);
|
|
||||||
this.scrollTimer = null;
|
|
||||||
},
|
|
||||||
// 移动端延迟重启滚动(触摸结束后1秒再重启)
|
|
||||||
startScrollDelayed() {
|
|
||||||
if (this.delayScrollTimer) clearTimeout(this.delayScrollTimer);
|
|
||||||
this.delayScrollTimer = setTimeout(() => {
|
|
||||||
this.startScroll();
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
nextScroll() {
|
|
||||||
if (this.broadcastList.length <= 1) return;
|
|
||||||
this.isTransition = true;
|
|
||||||
this.currentBroadcastIndex += 1;
|
|
||||||
// 如果到"克隆的第一条",0.5s后瞬间跳回真正的第一条
|
|
||||||
if (this.currentBroadcastIndex === this.broadcastList.length) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.isTransition = false;
|
|
||||||
this.currentBroadcastIndex = 0;
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (this.scrollTimer) clearInterval(this.scrollTimer);
|
|
||||||
if (this.delayScrollTimer) clearTimeout(this.delayScrollTimer);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
prefix-icon="el-icon-user"
|
prefix-icon="el-icon-user"
|
||||||
v-model="loginForm.userName"
|
v-model="loginForm.userName"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t('user.Account')"
|
:placeholder="$t('user.Account')"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -39,7 +38,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
@@ -52,7 +50,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="loginForm.code"
|
v-model="loginForm.code"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -135,7 +132,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
prefix-icon="el-icon-user"
|
prefix-icon="el-icon-user"
|
||||||
v-model="loginForm.userName"
|
v-model="loginForm.userName"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t('user.Account')"
|
:placeholder="$t('user.Account')"
|
||||||
type="email"
|
type="email"
|
||||||
@@ -145,7 +141,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
@@ -158,7 +153,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="loginForm.code"
|
v-model="loginForm.code"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -219,8 +213,6 @@ import {
|
|||||||
} from "../../api/login";
|
} from "../../api/login";
|
||||||
import { encryption } from "../../utils/fun";
|
import { encryption } from "../../utils/fun";
|
||||||
import { getAccountList } from "../../api/personalCenter";
|
import { getAccountList } from "../../api/personalCenter";
|
||||||
import { validatePassword, formatPasswordErrors } from "../../utils/passwordValidator";
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -264,155 +256,6 @@ export default {
|
|||||||
countDownTime: 60,
|
countDownTime: 60,
|
||||||
timer: null,
|
timer: null,
|
||||||
lang: "en",
|
lang: "en",
|
||||||
currencyList: [
|
|
||||||
{
|
|
||||||
path: "nexaAccess",
|
|
||||||
value: "nexa",
|
|
||||||
label: "nexa",
|
|
||||||
img: require("../../assets/img/currency-nexa.png"),
|
|
||||||
imgUrl: `${this.$baseApi}img/nexa.png`,
|
|
||||||
name: "course.NEXAcourse",
|
|
||||||
show: true,
|
|
||||||
amount: 10000,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "grsAccess",
|
|
||||||
value: "grs",
|
|
||||||
label: "grs",
|
|
||||||
img: require("../../assets/img/currency/grs.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/grs.svg`,
|
|
||||||
name: "course.GRScourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "monaAccess",
|
|
||||||
value: "mona",
|
|
||||||
label: "mona",
|
|
||||||
img: require("../../assets/img/currency/mona.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/mona.svg`,
|
|
||||||
name: "course.MONAcourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "dgbsAccess",
|
|
||||||
value: "dgbs",
|
|
||||||
// label: "dgb-skein-pool1",
|
|
||||||
label: "dgb(skein)",
|
|
||||||
img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/dgb.svg`,
|
|
||||||
name: "course.dgbsCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "dgbqAccess",
|
|
||||||
value: "dgbq",
|
|
||||||
// label: "dgb(qubit-pool1)",
|
|
||||||
label: "dgb(qubit)",
|
|
||||||
img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/dgb.svg`,
|
|
||||||
name: "course.dgbqCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "dgboAccess",
|
|
||||||
value: "dgbo",
|
|
||||||
// label: "dgb-odocrypt-pool1",
|
|
||||||
label: "dgb(odocrypt)",
|
|
||||||
img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/dgb.svg`,
|
|
||||||
name: "course.dgboCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "rxdAccess",
|
|
||||||
value: "rxd",
|
|
||||||
label: "radiant(rxd)",
|
|
||||||
img: require("../../assets/img/currency/rxd.png"),
|
|
||||||
imgUrl: `${this.$baseApi}img/rxd.png`,
|
|
||||||
name: "course.RXDcourse",
|
|
||||||
show: true,
|
|
||||||
amount: 100,
|
|
||||||
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// path: "enxAccess",
|
|
||||||
// value: "enx",
|
|
||||||
// label: "Entropyx(enx)",
|
|
||||||
// img: require("../../assets/img/currency/enx.svg"),
|
|
||||||
// imgUrl: `${this.$baseApi}img/enx.svg`,
|
|
||||||
// name: "course.ENXcourse",
|
|
||||||
// show: true,
|
|
||||||
// amount: 5000,
|
|
||||||
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
path: "alphminingPool",
|
|
||||||
value: "alph",
|
|
||||||
label: "alephium",
|
|
||||||
img: require("../../assets/img/currency/alph.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/alph.svg`,
|
|
||||||
name: "course.alphCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "xmr",
|
|
||||||
value: "monero",
|
|
||||||
label: "xmr",
|
|
||||||
img: require("../../assets/img/currency/xmr.png"),
|
|
||||||
imgUrl: `${this.$baseApi}img/xmr.png`,
|
|
||||||
name: "course.xmrCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "xtm",
|
|
||||||
value: "sha3x",
|
|
||||||
label: "xtm(sha3x)",
|
|
||||||
img: require("../../assets/img/currency/xtm.svg"),
|
|
||||||
imgUrl: `${this.$baseApi}img/xtm.svg`,
|
|
||||||
name: "course.xmrCourse",
|
|
||||||
show: true,
|
|
||||||
amount: 10000,
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// { //告知已删除此币种 Radiant
|
|
||||||
// value: "dgb2_odo",
|
|
||||||
// label: "dgb-odocrypt-pool2",
|
|
||||||
// img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
// imgUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/109.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value: "dgb_qubit_a10",
|
|
||||||
// label: "dgb-qubit-pool2",
|
|
||||||
// img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
// imgUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/109.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value: "dgb_skein_a10",
|
|
||||||
// label: "dgb-skein-pool2",
|
|
||||||
// img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
// imgUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/109.png",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// value: "dgb_odo_b20",
|
|
||||||
// label: "dgb-odoscrypt-pool3",
|
|
||||||
// img: require("../../assets/img/currency/DGB.svg"),
|
|
||||||
// imgUrl: "https://s2.coinmarketcap.com/static/img/coins/64x64/109.png",
|
|
||||||
// },
|
|
||||||
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -426,16 +269,6 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to) {
|
|
||||||
// 路由变化时自动同步语言和radio
|
|
||||||
const match = to.path.match(/^\/(zh|en)(\/|$)/);
|
|
||||||
if (match) {
|
|
||||||
this.radio = match[1];
|
|
||||||
this.lang = match[1];
|
|
||||||
this.$i18n.locale = match[1];
|
|
||||||
localStorage.setItem("lang", match[1]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$i18n.locale": function () {
|
"$i18n.locale": function () {
|
||||||
this.translate();
|
this.translate();
|
||||||
},
|
},
|
||||||
@@ -456,30 +289,10 @@ export default {
|
|||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$addStorageEvent(1, `currencyList`, JSON.stringify(this.currencyList))
|
this.lang = this.$i18n.locale; // 初始化语言值
|
||||||
// this.lang = this.$i18n.locale; // 初始化语言值
|
this.radio = localStorage.getItem("lang")
|
||||||
// this.radio = localStorage.getItem("lang")
|
? localStorage.getItem("lang")
|
||||||
// ? localStorage.getItem("lang")
|
: "en";
|
||||||
// : "en";
|
|
||||||
|
|
||||||
// 获取当前路由路径
|
|
||||||
const path = this.$route.path;
|
|
||||||
// 匹配 /zh/ 或 /en/ 作为语言前缀
|
|
||||||
const match = path.match(/^\/(zh|en)(\/|$)/);
|
|
||||||
if (match) {
|
|
||||||
this.radio = match[1];
|
|
||||||
this.lang = match[1];
|
|
||||||
this.$i18n.locale = match[1];
|
|
||||||
localStorage.setItem("lang", match[1]);
|
|
||||||
} else {
|
|
||||||
// fallback 到 localStorage 或 "en"
|
|
||||||
this.radio = localStorage.getItem("lang") || "en";
|
|
||||||
this.lang = this.radio;
|
|
||||||
this.$i18n.locale = this.radio;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
translate() {
|
translate() {
|
||||||
@@ -559,11 +372,6 @@ export default {
|
|||||||
JSON.stringify(data.data.access_token)
|
JSON.stringify(data.data.access_token)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// 等待一小段时间确保写入完成
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 50));
|
|
||||||
// 登录成功后
|
|
||||||
this.$bus.$emit('user-logged-in'); // 触发登录成功全局事件
|
|
||||||
this.fetchAccountList();
|
this.fetchAccountList();
|
||||||
this.fetchAccountGradeList();
|
this.fetchAccountGradeList();
|
||||||
this.fetchJurisdiction();
|
this.fetchJurisdiction();
|
||||||
@@ -716,16 +524,16 @@ export default {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码验证 - 使用优化后的详细校验逻辑
|
// 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&.*)
|
||||||
const validation = validatePassword(this.loginForm.password);
|
const regexPassword =
|
||||||
if (!validation.valid) {
|
/^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
||||||
// 生成友好的逐项错误提示
|
const PasswordIsValid = regexPassword.test(this.loginForm.password);
|
||||||
const errorMessage = formatPasswordErrors(validation.errors, this.$t.bind(this));
|
if (!PasswordIsValid) {
|
||||||
|
// 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||||
this.$message({
|
this.$message({
|
||||||
message: errorMessage,
|
message: this.$t(`user.PasswordReminder`),
|
||||||
type: "error",
|
type: "error",
|
||||||
showClose: true,
|
showClose: true,
|
||||||
duration: 5000, // 延长显示时间,因为错误信息可能有多条
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -741,38 +549,6 @@ export default {
|
|||||||
handleClick() {
|
handleClick() {
|
||||||
this.$router.push(`/${this.lang}`);
|
this.$router.push(`/${this.lang}`);
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 去除输入值中的空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @returns {string} 去除空格后的值
|
|
||||||
*/
|
|
||||||
removeSpaces(value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return value.replace(/\s/g, '');
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理邮箱输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleEmailInput(value) {
|
|
||||||
this.loginForm.userName = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handlePasswordInput(value) {
|
|
||||||
this.loginForm.password = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理验证码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleCodeInput(value) {
|
|
||||||
this.loginForm.code = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1346,13 +1346,6 @@ export default {
|
|||||||
this.getHistoryIncomeData(this.IncomeParams)
|
this.getHistoryIncomeData(this.IncomeParams)
|
||||||
this.getHistoryOutcomeData(this.OutcomeParams)
|
this.getHistoryOutcomeData(this.OutcomeParams)
|
||||||
|
|
||||||
|
|
||||||
this.registerRecoveryMethod('getMinerAccountInfoData', this.params);
|
|
||||||
this.registerRecoveryMethod('getMinerAccountPowerData', this.PowerParams);
|
|
||||||
this.registerRecoveryMethod('getAccountPowerDistributionData', this.PowerDistribution);
|
|
||||||
this.registerRecoveryMethod('getMinerListData', this.MinerListParams);
|
|
||||||
this.registerRecoveryMethod('getHistoryIncomeData', this.IncomeParams);
|
|
||||||
this.registerRecoveryMethod('getHistoryOutcomeData', this.OutcomeParams);
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
@@ -1407,12 +1400,11 @@ export default {
|
|||||||
// console.log(data,"获取币种信息");
|
// console.log(data,"获取币种信息");
|
||||||
},
|
},
|
||||||
async getMinerAccountPowerData(params) {
|
async getMinerAccountPowerData(params) {
|
||||||
// this.powerChartLoading = true
|
this.powerChartLoading = true
|
||||||
this.setLoading('powerChartLoading', true);
|
|
||||||
const data = await getMinerAccountPower(params)
|
const data = await getMinerAccountPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('powerChartLoading', false);
|
this.powerChartLoading = false
|
||||||
if (this.myChart) {
|
if (this.myChart) {
|
||||||
this.myChart.dispose()//销毁图表实列
|
this.myChart.dispose()//销毁图表实列
|
||||||
}
|
}
|
||||||
@@ -1445,13 +1437,13 @@ export default {
|
|||||||
this.option.series[1].data = rejectRate
|
this.option.series[1].data = rejectRate
|
||||||
|
|
||||||
this.inCharts()
|
this.inCharts()
|
||||||
this.setLoading('powerChartLoading', false);
|
this.powerChartLoading = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
async getAccountPowerDistributionData(params) {
|
async getAccountPowerDistributionData(params) {
|
||||||
this.setLoading('barChartLoading', true);
|
this.barChartLoading = true
|
||||||
const data = await getAccountPowerDistribution(params)
|
const data = await getAccountPowerDistribution(params)
|
||||||
let barData = data.data
|
let barData = data.data
|
||||||
let xData = []
|
let xData = []
|
||||||
@@ -1463,7 +1455,7 @@ export default {
|
|||||||
this.barOption.xAxis[0].data = xData
|
this.barOption.xAxis[0].data = xData
|
||||||
this.barOption.series[0].data = barValueList
|
this.barOption.series[0].data = barValueList
|
||||||
this.barInCharts()
|
this.barInCharts()
|
||||||
this.setLoading('barChartLoading', false);
|
this.barChartLoading = false
|
||||||
},
|
},
|
||||||
formatNumber(num) {//保留两位小数并补0
|
formatNumber(num) {//保留两位小数并补0
|
||||||
const intPart = Math.floor(num);
|
const intPart = Math.floor(num);
|
||||||
@@ -1471,7 +1463,7 @@ export default {
|
|||||||
return `${intPart}.${String(decimalPart).padStart(2, '0')}`;
|
return `${intPart}.${String(decimalPart).padStart(2, '0')}`;
|
||||||
},
|
},
|
||||||
async getMinerListData(params) {
|
async getMinerListData(params) {
|
||||||
this.setLoading('MinerListLoading', true);
|
this.MinerListLoading = true
|
||||||
const data = await getMinerList(params)
|
const data = await getMinerList(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.MinerListData = data.data
|
this.MinerListData = data.data
|
||||||
@@ -1511,7 +1503,7 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('MinerListLoading', false);
|
this.MinerListLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1570,11 +1562,11 @@ export default {
|
|||||||
// this.miniLoading=false
|
// this.miniLoading=false
|
||||||
// },
|
// },
|
||||||
getMinerPowerData:Debounce(async function(params){
|
getMinerPowerData:Debounce(async function(params){
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1626,18 +1618,62 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
},200),
|
},200),
|
||||||
|
//小图
|
||||||
|
// async getMinerPowerOnLine(params) {
|
||||||
|
// this.miniLoading=true
|
||||||
|
// const data = await getMinerPower(params)
|
||||||
|
|
||||||
|
// if (!data) {
|
||||||
|
// this.miniLoading=false
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// let miniData = data.data
|
||||||
|
// let xData = []
|
||||||
|
// let pv = []
|
||||||
|
// let rejectRate = []
|
||||||
|
|
||||||
|
// miniData.forEach(item => {
|
||||||
|
// if (item.date.includes(`T`)) {
|
||||||
|
// xData.push(`${item.date.split("T")[0]} ${item.date.split("T")[1].split(".")[0]}` )
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// xData.push(item.date)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pv.push(item.pv.toFixed(2))
|
||||||
|
// rejectRate.push((item.rejectRate * 100).toFixed(4))
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
// this.onLineOption.xAxis.data = xData
|
||||||
|
// this.onLineOption.series[0].data = pv
|
||||||
|
// this.onLineOption.series[1].data = rejectRate
|
||||||
|
// this.onLineOption.series[0].name= this.$t(`home.finallyPower`)
|
||||||
|
// this.onLineOption.series[1].name= this.$t(`home.rejectionRate`)
|
||||||
|
|
||||||
|
// this.ids = `Small${this.miniId}`
|
||||||
|
// this.miniChartOnLine = echarts.init(document.getElementById(this.ids))
|
||||||
|
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.miniChartOnLine.setOption(this.onLineOption,true);
|
||||||
|
// window.addEventListener("resize", () => {
|
||||||
|
// if (this.miniChartOnLine) this.miniChartOnLine.resize();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this.miniLoading=false
|
// this.miniLoading=false
|
||||||
// },
|
// },
|
||||||
getMinerPowerOnLine:Debounce(async function(params){
|
getMinerPowerOnLine:Debounce(async function(params){
|
||||||
|
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1680,7 +1716,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
|
|
||||||
|
|
||||||
},200),
|
},200),
|
||||||
@@ -1732,10 +1768,10 @@ export default {
|
|||||||
// this.miniLoading=false
|
// this.miniLoading=false
|
||||||
// },
|
// },
|
||||||
getMinerPowerOffLine:Debounce(async function(params){
|
getMinerPowerOffLine:Debounce(async function(params){
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1779,7 +1815,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
|
|
||||||
|
|
||||||
},200),
|
},200),
|
||||||
@@ -2192,12 +2228,6 @@ export default {
|
|||||||
case `alph`:
|
case `alph`:
|
||||||
window.open(`https://explorer.alephium.org/transactions/${txid}`)
|
window.open(`https://explorer.alephium.org/transactions/${txid}`)
|
||||||
break;
|
break;
|
||||||
case `xmr`:
|
|
||||||
window.open(`https://localmonero.co/blocks/tx/${txid}`)
|
|
||||||
break;
|
|
||||||
case `sha3x`:
|
|
||||||
window.open(`https://explore.tari.com/txs/${txid}`)
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
import { summaryOfPendingPayments } from "../../api/documentManagement";
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pendingPaymentData: [],
|
|
||||||
allPendingData: [],
|
|
||||||
currencyList: [
|
|
||||||
|
|
||||||
|
|
||||||
],
|
|
||||||
loading:false,
|
|
||||||
pendingPaymentParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
},
|
|
||||||
total: 0,
|
|
||||||
pageSizes: [10, 50, 200],
|
|
||||||
currentPage: 1,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
|
||||||
window.addEventListener("setItem", () => {
|
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
|
||||||
});
|
|
||||||
this.fetchPendingPaymentData(this.pendingPaymentParams);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchPendingPaymentData(params) {
|
|
||||||
this.setLoading('loading', true);
|
|
||||||
const firstRes = await summaryOfPendingPayments(params);
|
|
||||||
let allRows = [];
|
|
||||||
if (firstRes && firstRes.code == 200) {
|
|
||||||
const firstRows = Array.isArray(firstRes.rows) ? firstRes.rows : [];
|
|
||||||
const total = Number(firstRes.total || 0);
|
|
||||||
// 若后端做了分页,二次拉取全量数据用于前端全局排序与分页
|
|
||||||
if (total > params.pageSize) {
|
|
||||||
const fullRes = await summaryOfPendingPayments({ ...params, pageNum: 1, pageSize: total });
|
|
||||||
allRows = Array.isArray(fullRes && fullRes.rows) ? fullRes.rows : firstRows;
|
|
||||||
} else {
|
|
||||||
allRows = firstRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortedRows = this.sortRows(allRows);
|
|
||||||
this.allPendingData = sortedRows;
|
|
||||||
this.total = sortedRows.length;
|
|
||||||
this.applySlice();
|
|
||||||
}
|
|
||||||
this.setLoading('loading', false);
|
|
||||||
},
|
|
||||||
sortRows(rows) {
|
|
||||||
const safeRows = Array.isArray(rows) ? rows : [];
|
|
||||||
return safeRows.slice().sort((a, b) => {
|
|
||||||
const aNeed = Number(a && a.needPayAmount != null ? a.needPayAmount : 0);
|
|
||||||
const aStart = Number(a && a.startPayAmount != null ? a.startPayAmount : 0);
|
|
||||||
const bNeed = Number(b && b.needPayAmount != null ? b.needPayAmount : 0);
|
|
||||||
const bStart = Number(b && b.startPayAmount != null ? b.startPayAmount : 0);
|
|
||||||
|
|
||||||
const aPriority = aNeed >= aStart ? 1 : 0;
|
|
||||||
const bPriority = bNeed >= bStart ? 1 : 0;
|
|
||||||
if (bPriority !== aPriority) return bPriority - aPriority;
|
|
||||||
if (bNeed !== aNeed) return bNeed - aNeed;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
applySlice() {
|
|
||||||
const pageSize = Number(this.pendingPaymentParams.pageSize || 10);
|
|
||||||
const pageNum = Number(this.pendingPaymentParams.pageNum || 1);
|
|
||||||
const start = (pageNum - 1) * pageSize;
|
|
||||||
const end = start + pageSize;
|
|
||||||
this.pendingPaymentData = (this.allPendingData || []).slice(start, end);
|
|
||||||
},
|
|
||||||
handelImg(coin) {
|
|
||||||
console.log(coin,"coin");
|
|
||||||
|
|
||||||
if(coin == "enx"){
|
|
||||||
const imgUrl = `${this.$baseApi}img/enx.svg`;
|
|
||||||
|
|
||||||
return imgUrl;
|
|
||||||
}
|
|
||||||
if(this.currencyList &&this.currencyList.length > 0 && coin){
|
|
||||||
return this.currencyList.find(item => item.value === coin)?.imgUrl || '';
|
|
||||||
}else{
|
|
||||||
return '';
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelCoinLabel(coin) {
|
|
||||||
if(coin == "enx"){
|
|
||||||
return "Entropyx(enx)";
|
|
||||||
}
|
|
||||||
if(this.currencyList &&this.currencyList.length > 0 && coin){
|
|
||||||
return this.currencyList.find(item => item.value === coin)?.label || '';
|
|
||||||
}else{
|
|
||||||
return coin;
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handelTime(time) {
|
|
||||||
try {
|
|
||||||
return `${time.split("T")[0]} ${time.split("T")[1].split(".")[0]}`
|
|
||||||
} catch (error) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSizeChange(val) {
|
|
||||||
console.log(`每页 ${val} 条`);
|
|
||||||
this.pendingPaymentParams.pageSize = val
|
|
||||||
this.pendingPaymentParams.pageNum = 1
|
|
||||||
this.currentPage = 1
|
|
||||||
if (this.allPendingData && this.allPendingData.length > 0) {
|
|
||||||
this.applySlice();
|
|
||||||
} else {
|
|
||||||
this.fetchPendingPaymentData(this.pendingPaymentParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
handleCurrentChange(val) {
|
|
||||||
console.log(`当前页: ${val}`);
|
|
||||||
this.pendingPaymentParams.pageNum = val
|
|
||||||
if (this.allPendingData && this.allPendingData.length > 0) {
|
|
||||||
this.applySlice();
|
|
||||||
} else {
|
|
||||||
this.fetchPendingPaymentData(this.pendingPaymentParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div v-loading="loading">
|
|
||||||
|
|
||||||
<div class="main-title">{{$t('backendSystem.pendingPaymentSummary')}}</div>
|
|
||||||
<el-table
|
|
||||||
:data="pendingPaymentData"
|
|
||||||
border
|
|
||||||
style="width: 100%; margin-bottom: 18px"
|
|
||||||
:header-cell-style="{ 'text-align': 'left' }"
|
|
||||||
:cell-style="{ 'text-align': 'left' }"
|
|
||||||
height="60vh"
|
|
||||||
>
|
|
||||||
<el-table-column prop="coin" :label="$t('backendSystem.coin2')" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope" >
|
|
||||||
<div style="display: flex; align-items: center;justify-content: left;">
|
|
||||||
<img :src="handelImg(scope.row.coin)" style="width: 20px" />
|
|
||||||
<span style="margin-left: 5px">{{ handelCoinLabel(scope.row.coin) }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="user" :label="$t('backendSystem.minerUser2')" show-overflow-tooltip/>
|
|
||||||
<el-table-column prop="shouldOutDate" :label="$t('backendSystem.AllocateTime')" show-overflow-tooltip >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ handelTime(scope.row.shouldOutDate ) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="maxHeight" :label="$t('backendSystem.allocateHeight')" show-overflow-tooltip/>
|
|
||||||
<el-table-column prop="startPayAmount" :label="$t('backendSystem.startPayAmount')" show-overflow-tooltip/>
|
|
||||||
|
|
||||||
<el-table-column prop="needPayAmount" :label="$t('backendSystem.needPayAmount')" show-overflow-tooltip>
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span :class="{ 'amount-highlight': Number(scope.row.needPayAmount) >= Number(scope.row.startPayAmount) }">
|
|
||||||
{{ scope.row.needPayAmount }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24" style="display: flex; justify-content: center;">
|
|
||||||
<el-pagination
|
|
||||||
style="margin:0 auto;margin-top: 10px;"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
:current-page.sync="currentPage"
|
|
||||||
:page-sizes="pageSizes"
|
|
||||||
:page-size="pendingPaymentParams.pageSize"
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
:total="total">
|
|
||||||
</el-pagination>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Index from "./index";
|
|
||||||
export default {
|
|
||||||
mixins: [Index],
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.main-title {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
.amount-highlight {
|
|
||||||
font-weight: 700;
|
|
||||||
color: #f56c6c;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -96,20 +96,17 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.fetchApiList(this.listParams)
|
this.fetchApiList(this.listParams)
|
||||||
this.registerRecoveryMethod('fetchApiList', this.listParams);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchApiKey(params) {
|
async fetchApiKey(params) {
|
||||||
this.ApiKeyLoading = true
|
this.ApiKeyLoading = true
|
||||||
this.setLoading('ApiKeyLoading', true);
|
|
||||||
const data = await getApiKey(params)
|
const data = await getApiKey(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.fetchApiList(this.listParams)
|
this.fetchApiList(this.listParams)
|
||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('ApiKeyLoading', false);
|
this.ApiKeyLoading = false
|
||||||
},
|
},
|
||||||
async fetchApiList(params) {
|
async fetchApiList(params) {
|
||||||
this.apiPageLoading = true
|
this.apiPageLoading = true
|
||||||
@@ -118,7 +115,7 @@ export default {
|
|||||||
this.apiList = data.rows
|
this.apiList = data.rows
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('apiPageLoading', false);
|
this.apiPageLoading = false
|
||||||
},
|
},
|
||||||
async fetchApiInfo(params) {
|
async fetchApiInfo(params) {
|
||||||
this.apiPageLoading = true
|
this.apiPageLoading = true
|
||||||
@@ -130,7 +127,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('apiPageLoading', false);
|
this.apiPageLoading = false
|
||||||
},
|
},
|
||||||
async fetchUpdateAPI(params) {
|
async fetchUpdateAPI(params) {
|
||||||
this.apiPageLoading = true
|
this.apiPageLoading = true
|
||||||
@@ -140,7 +137,7 @@ export default {
|
|||||||
this.modifyDialogVisible =false
|
this.modifyDialogVisible =false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('apiPageLoading', false);
|
this.apiPageLoading = false
|
||||||
},
|
},
|
||||||
async fetchDelApi(params) {
|
async fetchDelApi(params) {
|
||||||
this.apiPageLoading = true
|
this.apiPageLoading = true
|
||||||
@@ -152,7 +149,7 @@ export default {
|
|||||||
this.fetchApiList(this.listParams)
|
this.fetchApiList(this.listParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('apiPageLoading', false);
|
this.apiPageLoading = false
|
||||||
},
|
},
|
||||||
RequestApiKey() {
|
RequestApiKey() {
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
import { getCheck,getAddBalace, getAddMinerAccount, getAccountList, getDelMinerAccount, getMinerAccountBalance, getCheckAccount,getCheckBalance,getIfBind } from "../../../api/personalCenter"
|
import { getCheck,getAddBalace, getAddMinerAccount, getAccountList, getDelMinerAccount, getMinerAccountBalance, getCheckAccount,getCheckBalance,getIfBind } from "../../../api/personalCenter"
|
||||||
import {getAccountGradeList } from "../../../api/login"
|
import {getAccountGradeList } from "../../../api/login"
|
||||||
import { Debounce,throttle }from "../../../utils/publicMethods";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -209,7 +208,7 @@ export default {
|
|||||||
addMinerLoading:false,
|
addMinerLoading:false,
|
||||||
screenCurrency:"",
|
screenCurrency:"",
|
||||||
newAccountList:[],
|
newAccountList:[],
|
||||||
quotaList:[//起付额
|
quotaList:[
|
||||||
|
|
||||||
{
|
{
|
||||||
value:"nexa",
|
value:"nexa",
|
||||||
@@ -246,28 +245,16 @@ export default {
|
|||||||
amount:100,
|
amount:100,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value:"enx",
|
||||||
|
amount:5000,
|
||||||
|
|
||||||
// {
|
},
|
||||||
// value:"enx",
|
|
||||||
// amount:5000,
|
|
||||||
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
value:"alph",
|
value:"alph",
|
||||||
amount:1,
|
amount:1,
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
|
||||||
value:"monero",
|
|
||||||
amount:0.1,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value:"sha3x",
|
|
||||||
amount:10000,
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
amount:1,
|
amount:1,
|
||||||
@@ -283,9 +270,6 @@ export default {
|
|||||||
|
|
||||||
this.fetchAccountList()
|
this.fetchAccountList()
|
||||||
|
|
||||||
this.registerRecoveryMethod('fetchIfBind', "");
|
|
||||||
this.registerRecoveryMethod('fetchAccountList', "");
|
|
||||||
|
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
||||||
window.addEventListener("setItem", () => {
|
window.addEventListener("setItem", () => {
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
||||||
@@ -300,8 +284,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchIfBind(params){
|
async fetchIfBind(params){
|
||||||
// this.securityLoading = true
|
this.securityLoading = true
|
||||||
this.setLoading('securityLoading', true);
|
|
||||||
const data = await getIfBind(params)
|
const data = await getIfBind(params)
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
@@ -319,14 +302,13 @@ export default {
|
|||||||
this.dialogVerification=true
|
this.dialogVerification=true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setLoading('securityLoading', false);
|
this.securityLoading = false
|
||||||
},
|
},
|
||||||
async fetchCheck(params){
|
async fetchCheck(params){
|
||||||
// this.addMinerLoading =true
|
this.addMinerLoading =true
|
||||||
this.setLoading('addMinerLoading', true);
|
|
||||||
const data = await getCheck(params)
|
const data = await getCheck(params)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading =false
|
||||||
|
|
||||||
}
|
}
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
@@ -338,21 +320,20 @@ export default {
|
|||||||
type: "error",
|
type: "error",
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
});
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading =false
|
||||||
}else if(data.code === 802){//钱包不可用
|
}else if(data.code === 802){//钱包不可用
|
||||||
this.$message({
|
this.$message({
|
||||||
message: this.$t(`personal.invalidAddress`),
|
message: this.$t(`personal.invalidAddress`),
|
||||||
type: "error",
|
type: "error",
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
});
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading =false
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchCheckBalance(params){
|
async fetchCheckBalance(params){
|
||||||
// this.confirmBindingLoading =true
|
this.confirmBindingLoading =true
|
||||||
this.setLoading('confirmBindingLoading', true);
|
|
||||||
const data = await getCheckBalance(params)
|
const data = await getCheckBalance(params)
|
||||||
if (data && data.data) {
|
if (data && data.data) {
|
||||||
this.fetchWalletAddress(this.WalletAddressParams)
|
this.fetchWalletAddress(this.WalletAddressParams)
|
||||||
@@ -363,7 +344,7 @@ export default {
|
|||||||
type: 'error'
|
type: 'error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.setLoading('confirmBindingLoading', false);
|
this.confirmBindingLoading =false
|
||||||
},
|
},
|
||||||
async fetchAccountGradeList(){
|
async fetchAccountGradeList(){
|
||||||
const data = await getAccountGradeList()
|
const data = await getAccountGradeList()
|
||||||
@@ -388,8 +369,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchMinerAccountBalance(params) {
|
async fetchMinerAccountBalance(params) {
|
||||||
// this.MiningLoading = true
|
this.MiningLoading = true
|
||||||
this.setLoading('MiningLoading', true);
|
|
||||||
const data = await getMinerAccountBalance(params)
|
const data = await getMinerAccountBalance(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.walletDialogVisible = true
|
this.walletDialogVisible = true
|
||||||
@@ -406,11 +386,10 @@ export default {
|
|||||||
this.paymentSettingsData.active = this.paymentSettingsData.active==`1` ? this.$t(`personal.no`) :this.$t(`personal.yes`)
|
this.paymentSettingsData.active = this.paymentSettingsData.active==`1` ? this.$t(`personal.no`) :this.$t(`personal.yes`)
|
||||||
|
|
||||||
this.paymentSettingsData.amount = this.paymentSettingsData.amount ? this.paymentSettingsData.amount : `0`
|
this.paymentSettingsData.amount = this.paymentSettingsData.amount ? this.paymentSettingsData.amount : `0`
|
||||||
this.setLoading('MiningLoading', false);
|
this.MiningLoading = false
|
||||||
},
|
},
|
||||||
async fetchDelMinerAccount(params) {
|
async fetchDelMinerAccount(params) {
|
||||||
// this.MiningLoading = true
|
this.MiningLoading = true
|
||||||
this.setLoading('MiningLoading', true);
|
|
||||||
const data = await getDelMinerAccount(params)
|
const data = await getDelMinerAccount(params)
|
||||||
|
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
@@ -421,18 +400,17 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
this.setLoading('MiningLoading', false);
|
this.MiningLoading = false
|
||||||
},
|
},
|
||||||
async fetchAccountList(params) {
|
async fetchAccountList(params) {
|
||||||
// this.MiningLoading = true
|
this.MiningLoading = true
|
||||||
this.setLoading('MiningLoading', true);
|
|
||||||
const data = await getAccountList(params)
|
const data = await getAccountList(params)
|
||||||
this.accountList = data.data
|
this.accountList = data.data
|
||||||
console.log("请求成功,",data);
|
console.log("请求成功,",data);
|
||||||
this.newAccountList = this.accountList
|
this.newAccountList = this.accountList
|
||||||
this.$addStorageEvent(1, `accountList`, JSON.stringify(this.accountList))
|
this.$addStorageEvent(1, `accountList`, JSON.stringify(this.accountList))
|
||||||
|
|
||||||
this.setLoading('MiningLoading', false);
|
this.MiningLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -453,8 +431,7 @@ export default {
|
|||||||
},
|
},
|
||||||
//添加挖矿账户
|
//添加挖矿账户
|
||||||
async fetchAddMinerAccount(params) {
|
async fetchAddMinerAccount(params) {
|
||||||
// this.addMinerLoading =true
|
this.addMinerLoading =true
|
||||||
this.setLoading('addMinerLoading', true);
|
|
||||||
const data = await getAddMinerAccount(params)
|
const data = await getAddMinerAccount(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -474,7 +451,7 @@ export default {
|
|||||||
this.fetchAccountList()
|
this.fetchAccountList()
|
||||||
this.fetchAccountGradeList()
|
this.fetchAccountGradeList()
|
||||||
|
|
||||||
this.setLoading('addMinerLoading', false);
|
this.addMinerLoading =false
|
||||||
},
|
},
|
||||||
handleCheckAllChange(val) {
|
handleCheckAllChange(val) {
|
||||||
|
|
||||||
@@ -555,7 +532,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
confirmAdd:Debounce(function(){
|
confirmAdd() {
|
||||||
|
// this.accountList.push({
|
||||||
|
// account: this.params.account,
|
||||||
|
// miningPool: this.params.miningPool,
|
||||||
|
// currency: this.params.miningPool,
|
||||||
|
// remarks: this.params.remarks,
|
||||||
|
// })
|
||||||
if (!this.AccountParams.ma) {
|
if (!this.AccountParams.ma) {
|
||||||
this.$message({
|
this.$message({
|
||||||
message: this.$t(`personal.accountNumber`),
|
message: this.$t(`personal.accountNumber`),
|
||||||
@@ -607,66 +590,12 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.fetchCheck({ coin: this.AccountParams.coin, ma: this.AccountParams.ma,balance: this.AccountParams.balance})
|
this.fetchCheck({ coin: this.AccountParams.coin, ma: this.AccountParams.ma,balance: this.AccountParams.balance})
|
||||||
},200),
|
// this.fetchCheckAccount({ coin: this.AccountParams.coin, ma: this.AccountParams.ma })
|
||||||
// confirmAdd() {
|
|
||||||
|
|
||||||
// if (!this.AccountParams.ma) {
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`personal.accountNumber`),
|
|
||||||
// type: "error",
|
|
||||||
// showClose: true
|
|
||||||
// });
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if (!this.AccountParams.balance) {
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`personal.inputWalletAddress`),
|
|
||||||
// type: "error",
|
|
||||||
// showClose: true
|
|
||||||
// });
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if (!this.AccountParams.coin) {
|
|
||||||
// this.$message({
|
|
||||||
// message:this.$t(`personal.selectCurrency`),
|
|
||||||
// type: "error",
|
|
||||||
// showClose: true
|
|
||||||
// });
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!this.AccountParams.code && this.isItBound) {
|
|
||||||
// this.$message({
|
|
||||||
// showClose: true,
|
|
||||||
// message: this.$t(`personal.gCode`),
|
|
||||||
// type: 'error'
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 账户只能输入字母、数字、下划线,且不能以数字开头,长度不小于4位,不大于24位
|
|
||||||
// const regexAccount=/^[a-zA-Z_][a-zA-Z0-9_]{3,23}$/
|
|
||||||
|
|
||||||
// const PasswordIsValid = regexAccount.test(this.AccountParams.ma);
|
|
||||||
// if (!PasswordIsValid) {
|
|
||||||
// // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`personal.accountFormat`),
|
|
||||||
// type: "error",
|
|
||||||
// showClose: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// this.fetchCheck({ coin: this.AccountParams.coin, ma: this.AccountParams.ma,balance: this.AccountParams.balance})
|
|
||||||
// // this.fetchCheckAccount({ coin: this.AccountParams.coin, ma: this.AccountParams.ma })
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// },
|
},
|
||||||
handelAddClose(){
|
handelAddClose(){
|
||||||
for (let key in this.AccountParams) {
|
for (let key in this.AccountParams) {
|
||||||
this.AccountParams[key] = "";
|
this.AccountParams[key] = "";
|
||||||
@@ -727,7 +656,6 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
this.handelQuotaList(item.coin)
|
this.handelQuotaList(item.coin)
|
||||||
|
|
||||||
this.WalletAddressParams.ma = item.ma
|
this.WalletAddressParams.ma = item.ma
|
||||||
this.WalletAddressParams.coin = item.coin
|
this.WalletAddressParams.coin = item.coin
|
||||||
|
|
||||||
|
|||||||
@@ -197,16 +197,14 @@ export default {
|
|||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
console.log( this.newMiningAccountList,"isrjiojfeo");
|
||||||
|
|
||||||
|
|
||||||
this.fetchUrlList(this.UrlListParams)
|
this.fetchUrlList(this.UrlListParams)
|
||||||
this.registerRecoveryMethod('fetchUrlList', this.UrlListParams);
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchHtmlUrl(params){
|
async fetchHtmlUrl(params){
|
||||||
// this.establishLoading = true
|
this.establishLoading = true
|
||||||
this.setLoading('establishLoading', true);
|
|
||||||
const data = await getHtmlUrl(params)
|
const data = await getHtmlUrl(params)
|
||||||
|
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
@@ -214,11 +212,10 @@ export default {
|
|||||||
this.dialogVisible=false
|
this.dialogVisible=false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('establishLoading', false);
|
this.establishLoading = false
|
||||||
},
|
},
|
||||||
async fetchUrlList(params){
|
async fetchUrlList(params){
|
||||||
// this.UrlListLoading = true
|
this.UrlListLoading = true
|
||||||
this.setLoading('UrlListLoading', true);
|
|
||||||
const data = await getUrlList(params)
|
const data = await getUrlList(params)
|
||||||
console.log(data,666 );
|
console.log(data,666 );
|
||||||
|
|
||||||
@@ -226,7 +223,7 @@ export default {
|
|||||||
|
|
||||||
this.TotalSize = data.total
|
this.TotalSize = data.total
|
||||||
|
|
||||||
this.setLoading('UrlListLoading', false);
|
this.UrlListLoading = false
|
||||||
},
|
},
|
||||||
async fetchUrlInfo(params){
|
async fetchUrlInfo(params){
|
||||||
const data = await getUrlInfo(params)
|
const data = await getUrlInfo(params)
|
||||||
@@ -242,8 +239,7 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
async fetchChangeUrlInfo(params){
|
async fetchChangeUrlInfo(params){
|
||||||
// this.modifyLoading=true
|
this.modifyLoading=true
|
||||||
this.setLoading('modifyLoading', true);
|
|
||||||
const data = await getChangeUrlInfo(params)
|
const data = await getChangeUrlInfo(params)
|
||||||
console.log(data);
|
console.log(data);
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
@@ -252,7 +248,7 @@ export default {
|
|||||||
console.log("修改成功");
|
console.log("修改成功");
|
||||||
|
|
||||||
}
|
}
|
||||||
this.setLoading('modifyLoading', false);
|
this.modifyLoading=false
|
||||||
|
|
||||||
},
|
},
|
||||||
async fetchDelete(params){
|
async fetchDelete(params){
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { getIfBind, getBindInfo, getBindGoogle, getBindCode, getCloseStepTwo, getCloseCode, getUpdatePwd, getUpdatePwdCode } from "../../../api/personalCenter"
|
import { getIfBind, getBindInfo, getBindGoogle, getBindCode, getCloseStepTwo, getCloseCode, getUpdatePwd, getUpdatePwdCode } from "../../../api/personalCenter"
|
||||||
import { encryption } from "../../../utils/fun";
|
import { encryption } from "../../../utils/fun";
|
||||||
import { getResetPwd, getResetPwdCode, sendCloseAccount, closeAccount } from "../../../api/login"
|
import { getResetPwd, getResetPwdCode } from "../../../api/login"
|
||||||
import { validatePassword, formatPasswordErrors } from "../../../utils/passwordValidator";
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -11,7 +10,6 @@ export default {
|
|||||||
confirmationVerification: false,
|
confirmationVerification: false,
|
||||||
maintainDialogVisible: false,
|
maintainDialogVisible: false,
|
||||||
deleteAccountDialog: false,
|
deleteAccountDialog: false,
|
||||||
deleteAccountWarningDialog: false, // 删除账户前未开启双重验证的提示弹窗
|
|
||||||
params: {
|
params: {
|
||||||
gCode: "",
|
gCode: "",
|
||||||
eCode: "",
|
eCode: "",
|
||||||
@@ -99,18 +97,6 @@ export default {
|
|||||||
countDownTimePassword: 60,
|
countDownTimePassword: 60,
|
||||||
timerPassword: null,
|
timerPassword: null,
|
||||||
lang:"zh",
|
lang:"zh",
|
||||||
// 删除账户相关
|
|
||||||
deleteAccountParams: {
|
|
||||||
eCode: "",
|
|
||||||
gCode: "",
|
|
||||||
},
|
|
||||||
btnDisabledDeleteAccount: false,
|
|
||||||
bthTextDeleteAccount: "user.obtainVerificationCode",
|
|
||||||
countDownTimeDeleteAccount: 60,
|
|
||||||
timerDeleteAccount: null,
|
|
||||||
deleteAccountLoading: false,
|
|
||||||
deleteAccountCodeLoading: false, // 获取验证码按钮loading状态
|
|
||||||
userEmail: "",
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -164,28 +150,18 @@ export default {
|
|||||||
this.bthTextPassword = `user.again`
|
this.bthTextPassword = `user.again`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.sessionStorage.getItem("deleteAccount_time")) {
|
|
||||||
this.countDownTimeDeleteAccount = Number(window.sessionStorage.getItem("deleteAccount_time"));
|
|
||||||
this.startCountDownDeleteAccount()
|
|
||||||
this.btnDisabledDeleteAccount = true;
|
|
||||||
this.bthTextDeleteAccount = `user.again`
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
||||||
this.lang = this.$i18n.locale; // 初始化语言值
|
this.lang = this.$i18n.locale; // 初始化语言值
|
||||||
this.fetchIfBind()
|
this.fetchIfBind()
|
||||||
this.registerRecoveryMethod('fetchIfBind', "");
|
|
||||||
if (this.$route.params.active) {
|
if (this.$route.params.active) {
|
||||||
this.handelVerification()
|
this.handelVerification()
|
||||||
}
|
}
|
||||||
// 获取用户邮箱
|
|
||||||
this.getUserEmail();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchIfBind(params) {
|
async fetchIfBind(params) {
|
||||||
this.setLoading('securityLoading', true);
|
this.securityLoading = true
|
||||||
const data = await getIfBind(params)
|
const data = await getIfBind(params)
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
@@ -194,10 +170,10 @@ export default {
|
|||||||
this.isItBound = false
|
this.isItBound = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setLoading('securityLoading', false);
|
this.securityLoading = false
|
||||||
},
|
},
|
||||||
async fetchBindInfo(params) {
|
async fetchBindInfo(params) {
|
||||||
this.setLoading('BindInfoLoading', true);
|
this.BindInfoLoading = true
|
||||||
const data = await getBindInfo(params)
|
const data = await getBindInfo(params)
|
||||||
console.log(data, "绑定信息");
|
console.log(data, "绑定信息");
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
@@ -206,10 +182,10 @@ export default {
|
|||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('BindInfoLoading', false);
|
this.BindInfoLoading = false
|
||||||
},
|
},
|
||||||
async fetchBindGoogle(params) {
|
async fetchBindGoogle(params) {
|
||||||
this.setLoading('BindInfoLoading', true);
|
this.BindInfoLoading = true
|
||||||
const data = await getBindGoogle(params)
|
const data = await getBindGoogle(params)
|
||||||
console.log(data, "绑定");
|
console.log(data, "绑定");
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
@@ -227,7 +203,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
this.setLoading('BindInfoLoading', false);
|
this.BindInfoLoading = false
|
||||||
},
|
},
|
||||||
async fetchBindCode(params) {
|
async fetchBindCode(params) {
|
||||||
const data = await getBindCode(params)
|
const data = await getBindCode(params)
|
||||||
@@ -240,7 +216,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchResetPwd(params) {
|
async fetchResetPwd(params) {
|
||||||
this.setLoading('ResetPwdLoading', true);
|
this.ResetPwdLoading = true
|
||||||
const data = await getUpdatePwd(params)
|
const data = await getUpdatePwd(params)
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -252,11 +228,9 @@ export default {
|
|||||||
this.dialogVisible = false
|
this.dialogVisible = false
|
||||||
this.verificationDialogVisible = false
|
this.verificationDialogVisible = false
|
||||||
localStorage.removeItem("token")
|
localStorage.removeItem("token")
|
||||||
// 修改密码成功后跳转到登录页面
|
|
||||||
const lang = this.$i18n.locale || this.lang || 'zh';
|
|
||||||
this.$router.push(`/${lang}/login`);
|
this.$router.push(`/${lang}/login`);
|
||||||
}
|
}
|
||||||
this.setLoading('ResetPwdLoading', false);
|
this.ResetPwdLoading = false
|
||||||
},
|
},
|
||||||
async fetchResetPwdCode(params) {
|
async fetchResetPwdCode(params) {
|
||||||
const data = await getUpdatePwdCode(params)
|
const data = await getUpdatePwdCode(params)
|
||||||
@@ -270,7 +244,7 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
async fetchCloseStepTwo(params) {
|
async fetchCloseStepTwo(params) {
|
||||||
this.setLoading('closeLoading', true);
|
this.closeLoading = true
|
||||||
const data = await getCloseStepTwo(params)
|
const data = await getCloseStepTwo(params)
|
||||||
if (data && data.code === 200) {
|
if (data && data.code === 200) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -286,7 +260,7 @@ export default {
|
|||||||
this.closeParams[key] = ""
|
this.closeParams[key] = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.setLoading('closeLoading', false);
|
this.closeLoading = false
|
||||||
},
|
},
|
||||||
async fetchCloseCode(params) {
|
async fetchCloseCode(params) {
|
||||||
const data = await getCloseCode(params)
|
const data = await getCloseCode(params)
|
||||||
@@ -315,13 +289,6 @@ export default {
|
|||||||
this.fetchBindInfo()
|
this.fetchBindInfo()
|
||||||
|
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 从删除账户提示弹窗跳转到开启双重验证
|
|
||||||
*/
|
|
||||||
jumpVerificationFromDelete() {
|
|
||||||
this.deleteAccountWarningDialog = false;
|
|
||||||
this.fetchBindInfo();
|
|
||||||
},
|
|
||||||
nextStep() {
|
nextStep() {
|
||||||
if (!this.checked) {
|
if (!this.checked) {
|
||||||
this.$message({
|
this.$message({
|
||||||
@@ -343,173 +310,8 @@ export default {
|
|||||||
this.maintainDialogVisible = true
|
this.maintainDialogVisible = true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
deleteAccount() {
|
||||||
* 获取用户邮箱
|
this.deleteAccountDialog = true
|
||||||
*/
|
|
||||||
getUserEmail() {
|
|
||||||
try {
|
|
||||||
const emailData = localStorage.getItem("userEmail");
|
|
||||||
if (emailData) {
|
|
||||||
const emailObj = JSON.parse(emailData);
|
|
||||||
// 如果是对象,尝试取常见的邮箱字段
|
|
||||||
this.userEmail = emailObj.email || emailObj.value || emailObj.userEmail || emailObj;
|
|
||||||
// 如果最终结果不是字符串,可能数据有问题
|
|
||||||
if (typeof this.userEmail !== "string") {
|
|
||||||
this.userEmail = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("获取用户邮箱失败:", e);
|
|
||||||
this.userEmail = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 打开删除账户弹窗(先检查是否开启双重验证)
|
|
||||||
*/
|
|
||||||
async deleteAccount() {
|
|
||||||
this.getUserEmail(); // 确保获取最新邮箱
|
|
||||||
// 先检查是否开启双重验证
|
|
||||||
await this.fetchIfBind();
|
|
||||||
// 如果未开启双重验证,显示提示弹窗
|
|
||||||
if (!this.isItBound) {
|
|
||||||
this.deleteAccountWarningDialog = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 如果已开启双重验证,正常打开删除账户弹窗
|
|
||||||
this.deleteAccountDialog = true;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 获取删除账户验证码
|
|
||||||
*/
|
|
||||||
async handelDeleteAccountCode() {
|
|
||||||
if (!this.userEmail) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: this.$t(`personal.mailbox`) + this.$t(`personal.pleaseEnter`),
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleteAccountCodeLoading = true;
|
|
||||||
try {
|
|
||||||
const data = await sendCloseAccount({ account: this.userEmail });
|
|
||||||
if (data && data.code === 200) {
|
|
||||||
this.$message({
|
|
||||||
message: this.$t(`user.codeSuccess`),
|
|
||||||
type: "success",
|
|
||||||
showClose: true
|
|
||||||
});
|
|
||||||
// 成功后开始倒计时
|
|
||||||
if (window.sessionStorage.getItem("deleteAccount_time") == null) {
|
|
||||||
this.startCountDownDeleteAccount()
|
|
||||||
} else {
|
|
||||||
this.countDownTimeDeleteAccount = Number(window.sessionStorage.getItem("deleteAccount_time"));
|
|
||||||
this.startCountDownDeleteAccount()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("获取删除账户验证码失败:", error);
|
|
||||||
this.$message({
|
|
||||||
message: this.$t(`user.codeFailed`) || '获取验证码失败',
|
|
||||||
type: "error",
|
|
||||||
showClose: true
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
this.deleteAccountCodeLoading = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 删除账户验证码倒计时
|
|
||||||
*/
|
|
||||||
startCountDownDeleteAccount() {
|
|
||||||
this.timerDeleteAccount = setInterval(() => {
|
|
||||||
if (this.countDownTimeDeleteAccount <= 1) {
|
|
||||||
clearInterval(this.timerDeleteAccount);
|
|
||||||
sessionStorage.removeItem("deleteAccount_time");
|
|
||||||
this.countDownTimeDeleteAccount = 60
|
|
||||||
this.btnDisabledDeleteAccount = false;
|
|
||||||
this.bthTextDeleteAccount = `user.obtainVerificationCode`
|
|
||||||
} else if (this.countDownTimeDeleteAccount > 0) {
|
|
||||||
this.countDownTimeDeleteAccount--;
|
|
||||||
this.btnDisabledDeleteAccount = true;
|
|
||||||
this.bthTextDeleteAccount = `user.again`
|
|
||||||
window.sessionStorage.setItem("deleteAccount_time", this.countDownTimeDeleteAccount);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 确认删除账户
|
|
||||||
*/
|
|
||||||
confirmDeleteAccount() {
|
|
||||||
if (!this.deleteAccountParams.eCode) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: this.$t(`personal.eCode`),
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!this.deleteAccountParams.gCode) {
|
|
||||||
this.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: this.$t(`personal.gCode`),
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 二次确认
|
|
||||||
this.$confirm(
|
|
||||||
this.$t(`personal.deleteAccountWarning`) || '删除后关于此账户的相关信息将不能恢复,请慎重操作!',
|
|
||||||
this.$t(`personal.Tips`) || '提示',
|
|
||||||
{
|
|
||||||
confirmButtonText: this.$t(`personal.determine`) || '确定',
|
|
||||||
cancelButtonText: this.$t(`personal.Cancel`) || '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}
|
|
||||||
).then(() => {
|
|
||||||
this.submitDeleteAccount();
|
|
||||||
}).catch(() => {
|
|
||||||
// 用户取消
|
|
||||||
});
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 提交删除账户请求
|
|
||||||
*/
|
|
||||||
async submitDeleteAccount() {
|
|
||||||
this.setLoading('deleteAccountLoading', true);
|
|
||||||
try {
|
|
||||||
const data = await closeAccount({
|
|
||||||
userEmail: this.userEmail,
|
|
||||||
eCode: this.deleteAccountParams.eCode,
|
|
||||||
gCode: this.deleteAccountParams.gCode
|
|
||||||
});
|
|
||||||
if (data && data.code === 200) {
|
|
||||||
this.$message({
|
|
||||||
message: this.$t(`personal.deleteAccountSuccess`) || '账户删除成功',
|
|
||||||
type: "success",
|
|
||||||
showClose: true
|
|
||||||
});
|
|
||||||
this.deleteAccountDialog = false;
|
|
||||||
// 清除本地存储并跳转到登录页
|
|
||||||
localStorage.removeItem("token");
|
|
||||||
localStorage.removeItem("userEmail");
|
|
||||||
const lang = this.$i18n.locale;
|
|
||||||
this.$router.push(`/${lang}/login`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("删除账户失败:", error);
|
|
||||||
}
|
|
||||||
this.setLoading('deleteAccountLoading', false);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 关闭删除账户弹窗
|
|
||||||
*/
|
|
||||||
closeDeleteAccountDialog() {
|
|
||||||
// 重置表单
|
|
||||||
this.deleteAccountParams.eCode = "";
|
|
||||||
this.deleteAccountParams.gCode = "";
|
|
||||||
},
|
},
|
||||||
handelVerification() {
|
handelVerification() {
|
||||||
// this.verificationDialogVisible = true
|
// this.verificationDialogVisible = true
|
||||||
@@ -620,16 +422,17 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码验证 - 使用优化后的详细校验逻辑
|
// 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*)
|
||||||
const validation = validatePassword(this.changePasswordParams.password);
|
const regexPassword =
|
||||||
if (!validation.valid) {
|
/^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
||||||
// 生成友好的逐项错误提示
|
|
||||||
const errorMessage = formatPasswordErrors(validation.errors, this.$t.bind(this));
|
const PasswordIsValid = regexPassword.test(this.changePasswordParams.password);
|
||||||
|
if (!PasswordIsValid) {
|
||||||
|
// 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||||
this.$message({
|
this.$message({
|
||||||
message: errorMessage,
|
message: this.$t(`user.PasswordReminder`),
|
||||||
type: "error",
|
type: "error",
|
||||||
showClose: true,
|
showClose: true
|
||||||
duration: 5000, // 延长显示时间,因为错误信息可能有多条
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -821,49 +624,6 @@ export default {
|
|||||||
// this.bthText="user.obtainVerificationCode"
|
// this.bthText="user.obtainVerificationCode"
|
||||||
// this.time = "";
|
// this.time = "";
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 去除输入值中的空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @returns {string} 去除空格后的值
|
|
||||||
*/
|
|
||||||
removeSpaces(value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return value.replace(/\s/g, '');
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @param {string} field - 字段名
|
|
||||||
*/
|
|
||||||
handlePasswordInput(value, field) {
|
|
||||||
const trimmedValue = this.removeSpaces(value);
|
|
||||||
if (field === 'password') {
|
|
||||||
this.changePasswordParams.password = trimmedValue;
|
|
||||||
} else if (field === 'newPassword') {
|
|
||||||
this.newPassword = trimmedValue;
|
|
||||||
} else if (field === 'pwd') {
|
|
||||||
this.params.pwd = trimmedValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理验证码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @param {string} field - 字段名
|
|
||||||
*/
|
|
||||||
handleCodeInput(value, field) {
|
|
||||||
const trimmedValue = this.removeSpaces(value);
|
|
||||||
if (field === 'updatePwdCode') {
|
|
||||||
this.changePasswordParams.updatePwdCode = trimmedValue;
|
|
||||||
} else if (field === 'eCode') {
|
|
||||||
this.closeParams.eCode = trimmedValue;
|
|
||||||
} else if (field === 'paramsECode') {
|
|
||||||
this.params.eCode = trimmedValue;
|
|
||||||
} else if (field === 'deleteAccountECode') {
|
|
||||||
this.deleteAccountParams.eCode = trimmedValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -62,23 +62,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="itemBox">
|
|
||||||
<div class="left">
|
|
||||||
<div>
|
|
||||||
<img src="../../../assets/img/deleteUser.png" alt="deleteUser" loading="lazy"/>
|
|
||||||
</div>
|
|
||||||
<div class="text">
|
|
||||||
<p>{{ $t(`personal.deleteAccount`) }}</p>
|
|
||||||
<p>{{ $t(`personal.deleteDescription`) }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<span class="modify" @click="deleteAccount">{{
|
|
||||||
$t(`personal.delete`)
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
@@ -145,18 +128,37 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<!-- <li >
|
||||||
<div class="topOneLeft">
|
<div class="topOneLeft">
|
||||||
<img src="../../../assets/img/deleteUser.png" alt="deleteUser" loading="lazy"/>
|
<img src="../../../assets/img/maintain.png" alt="">
|
||||||
|
<div class="text">
|
||||||
|
<span style="font-size: 1.1em;">{{$t(`personal.maintainPassword`)}}</span>
|
||||||
|
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.maintenanceInstructions`)}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="topOneRight2">
|
||||||
|
<el-button class="notEnabled">{{$t(`personal.notEnabled`)}}</el-button>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="modify" @click="maintainPassword">{{$t(`personal.Open`)}}</span>
|
||||||
|
</div>
|
||||||
|
</li> -->
|
||||||
|
<!-- <li >
|
||||||
|
<div class="topOneLeft">
|
||||||
|
<img src="../../../assets/img/deleteUser.png" alt="">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<span style="font-size: 1.1em;">{{$t(`personal.deleteAccount`)}}</span>
|
<span style="font-size: 1.1em;">{{$t(`personal.deleteAccount`)}}</span>
|
||||||
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.deleteDescription`)}}</span>
|
<span style="color: rgba(0,0,0,0.5);">{{$t(`personal.deleteDescription`)}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="topOneRight delete-btn">
|
<div class="topOneRight">
|
||||||
<span class="modify" id="deleteBtn" @click="deleteAccount">{{$t(`personal.delete`)}}</span>
|
|
||||||
|
<span class="modifyDelete" @click="deleteAccount"> <span class="bth"> {{$t(`personal.delete`)}}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
@@ -202,7 +204,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="email"
|
type="email"
|
||||||
v-model="changePasswordParams.updatePwdCode"
|
v-model="changePasswordParams.updatePwdCode"
|
||||||
@input="handleCodeInput($event, 'updatePwdCode')"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -224,7 +225,6 @@
|
|||||||
type="password"
|
type="password"
|
||||||
showPassword
|
showPassword
|
||||||
v-model="changePasswordParams.password"
|
v-model="changePasswordParams.password"
|
||||||
@input="handlePasswordInput($event, 'password')"
|
|
||||||
:placeholder="$t(`personal.pleaseEnter`)"
|
:placeholder="$t(`personal.pleaseEnter`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
<p class="remind" :title="$t(`user.passwordPrompt`)">
|
<p class="remind" :title="$t(`user.passwordPrompt`)">
|
||||||
@@ -238,10 +238,8 @@
|
|||||||
type="password"
|
type="password"
|
||||||
showPassword
|
showPassword
|
||||||
v-model="newPassword"
|
v-model="newPassword"
|
||||||
@input="handlePasswordInput($event, 'newPassword')"
|
|
||||||
:placeholder="$t(`personal.pleaseEnter`)"
|
:placeholder="$t(`personal.pleaseEnter`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!--
|
<!--
|
||||||
<div class="inputItem" v-if="isItBound">
|
<div class="inputItem" v-if="isItBound">
|
||||||
@@ -271,9 +269,8 @@
|
|||||||
<span class="title">{{ $t(`personal.verificationCode`) }}</span>
|
<span class="title">{{ $t(`personal.verificationCode`) }}</span>
|
||||||
<div class="verificationCode">
|
<div class="verificationCode">
|
||||||
<el-input
|
<el-input
|
||||||
type="text"
|
type="email"
|
||||||
v-model="closeParams.eCode"
|
v-model="closeParams.eCode"
|
||||||
@input="handleCodeInput($event, 'eCode')"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -374,7 +371,6 @@
|
|||||||
showPassword
|
showPassword
|
||||||
type="password"
|
type="password"
|
||||||
v-model="params.pwd"
|
v-model="params.pwd"
|
||||||
@input="handlePasswordInput($event, 'pwd')"
|
|
||||||
:placeholder="$t(`personal.pleaseEnter`)"
|
:placeholder="$t(`personal.pleaseEnter`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
</div>
|
</div>
|
||||||
@@ -384,7 +380,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="email"
|
type="email"
|
||||||
v-model="params.eCode"
|
v-model="params.eCode"
|
||||||
@input="handleCodeInput($event, 'paramsECode')"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -444,85 +439,51 @@
|
|||||||
</section>
|
</section>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 删除账户 -->
|
<!-- 删除账户 -->
|
||||||
<el-dialog
|
<el-dialog :visible.sync="deleteAccountDialog" width="35%">
|
||||||
:visible.sync="deleteAccountDialog"
|
<section class="dialogBox2">
|
||||||
width="40%"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
@close="closeDeleteAccountDialog"
|
|
||||||
>
|
|
||||||
<section class="verificationBox">
|
|
||||||
<div class="title">{{ $t(`personal.deleteAccount`) }}</div>
|
<div class="title">{{ $t(`personal.deleteAccount`) }}</div>
|
||||||
<div class="inputBox">
|
<div
|
||||||
<div class="inputItem">
|
class="deleteClauseBox"
|
||||||
<span class="title">{{ $t(`personal.mailbox`) }}</span>
|
v-for="item in clauseList"
|
||||||
<el-input
|
:key="item.title"
|
||||||
class="input"
|
>
|
||||||
:value="userEmail"
|
<h3>{{ item.title }}</h3>
|
||||||
disabled
|
<ul>
|
||||||
></el-input>
|
<li v-for="subItem in item.children" :key="subItem.label">
|
||||||
|
{{ subItem.label }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="inputItem">
|
<div class="dashedLine"></div>
|
||||||
<span class="title">{{ $t(`personal.verificationCode`) }}</span>
|
<div>
|
||||||
<div class="verificationCode">
|
<p>{{ $t(`personal.reasonForDeletion`) }}</p>
|
||||||
<el-input
|
<el-select
|
||||||
type="text"
|
v-model="value"
|
||||||
v-model="deleteAccountParams.eCode"
|
:placeholder="$t(`personal.select`)"
|
||||||
@input="handleCodeInput($event, 'deleteAccountECode')"
|
class="select"
|
||||||
autocomplete="off"
|
>
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
<el-option
|
||||||
></el-input>
|
v-for="item in reasonList"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="bthBox">
|
||||||
<el-button
|
<el-button
|
||||||
class="codeBtn deleteAccountCodeBtn"
|
style="width: 40%; font-size: 1.1em; margin-top: 30px"
|
||||||
:disabled="btnDisabledDeleteAccount"
|
@click="deleteAccountDialog = false"
|
||||||
:loading="deleteAccountCodeLoading"
|
>{{ $t(`personal.Cancel`) }}</el-button
|
||||||
@click="handelDeleteAccountCode"
|
|
||||||
>
|
>
|
||||||
<span
|
|
||||||
v-if="countDownTimeDeleteAccount < 60 && countDownTimeDeleteAccount > 0"
|
|
||||||
>{{ countDownTimeDeleteAccount }}</span
|
|
||||||
>{{ $t(bthTextDeleteAccount) }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="inputItem">
|
|
||||||
<span class="title">{{ $t(`personal.oneTimePassword`) }}</span>
|
|
||||||
<el-input
|
|
||||||
class="input"
|
|
||||||
type="number"
|
|
||||||
v-model="deleteAccountParams.gCode"
|
|
||||||
placeholder="000000"
|
|
||||||
></el-input>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="verificationBthBox deleteAccountBtnBox">
|
|
||||||
<el-button
|
<el-button
|
||||||
style=" margin: 0 auto"
|
style="width: 40%; font-size: 1.1em; margin-top: 30px"
|
||||||
:loading="deleteAccountLoading"
|
|
||||||
class="confirmBtn"
|
|
||||||
@click="confirmDeleteAccount"
|
|
||||||
>{{ $t(`personal.delete`) }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</el-dialog>
|
|
||||||
<!-- 删除账户前未开启双重验证提示弹窗 -->
|
|
||||||
<el-dialog
|
|
||||||
:visible.sync="deleteAccountWarningDialog"
|
|
||||||
width="35%"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<section class="dialogBox">
|
|
||||||
<div class="title">{{ $t(`personal.Tips`) }}</div>
|
|
||||||
<div class="verificationPrompt">
|
|
||||||
{{ $t(`personal.deleteAccountVerificationRequired`) }}
|
|
||||||
</div>
|
|
||||||
<el-button
|
|
||||||
class="dialogBth"
|
|
||||||
:loading="BindInfoLoading"
|
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="jumpVerificationFromDelete"
|
@click="deleteAccountDialog = false"
|
||||||
>{{ $t(`personal.goOpenIt`) }}</el-button
|
>{{ $t(`personal.determine`) }}</el-button
|
||||||
>
|
>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@@ -589,11 +550,6 @@ export default {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
.delete-btn {
|
|
||||||
background: #661fff;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right2{
|
.right2{
|
||||||
@@ -853,11 +809,6 @@ export default {
|
|||||||
padding: 6px 18px;
|
padding: 6px 18px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
.delete-btn {
|
|
||||||
background: #661fff;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.modifyDelete {
|
.modifyDelete {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
@@ -905,18 +856,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete-btn{
|
|
||||||
display: flex;
|
|
||||||
align-items: right !important;
|
|
||||||
// background: palevioletred;
|
|
||||||
justify-content: right !important;
|
|
||||||
padding-right: 3px;
|
|
||||||
#deleteBtn{
|
|
||||||
// background: palevioletred;
|
|
||||||
padding: 7px 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,19 +1109,6 @@ export default {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
// 删除账户获取验证码按钮样式
|
|
||||||
.deleteAccountCodeBtn {
|
|
||||||
background: #661fff;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
&:hover {
|
|
||||||
background: #5518e6;
|
|
||||||
}
|
|
||||||
&:disabled {
|
|
||||||
background: #ccc;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.bthBox {
|
.bthBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -1210,10 +1136,6 @@ export default {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
// 删除账户按钮更长
|
|
||||||
.deleteAccountBtnBox .el-button.confirmBtn {
|
|
||||||
min-width: 70% !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { findDataInfo ,documentsList} from '../../api/documentManagement'
|
|
||||||
export default {
|
export default {
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
@@ -66,15 +65,15 @@ export default {
|
|||||||
mode:"PPLNS+PROPDIF",
|
mode:"PPLNS+PROPDIF",
|
||||||
quota:"100",
|
quota:"100",
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// value:"enx",
|
value:"enx",
|
||||||
// label:"Entropyx(Enx)",
|
label:"Entropyx(Enx)",
|
||||||
// img:`${this.$baseApi}img/enx.svg`,
|
img:`${this.$baseApi}img/enx.svg`,
|
||||||
// rate:"1%",
|
rate:"0",
|
||||||
// address:"",
|
address:"",
|
||||||
// mode:"PPLNS+PROPDIF",
|
mode:"PPLNS+PROPDIF",
|
||||||
// quota:"5000",
|
quota:"5000",
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
value:"alph",
|
value:"alph",
|
||||||
label:"alephium(alph)",
|
label:"alephium(alph)",
|
||||||
@@ -89,76 +88,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
],
|
]
|
||||||
DetailsParams:{
|
}
|
||||||
lang:this.$i18n.locale,
|
|
||||||
childType:2,//1服务条款、2费率、3API文档 childType
|
|
||||||
id:'',
|
|
||||||
},
|
|
||||||
info:"",
|
|
||||||
rateLoading:false,
|
|
||||||
|
|
||||||
listParams:{
|
|
||||||
// type:"1",//挖矿教程
|
|
||||||
lang:this.$i18n.locale,
|
|
||||||
pageNum:1,
|
|
||||||
pageSize:50,
|
|
||||||
childType:2,//1服务条款、2费率、3API文档 childType
|
|
||||||
},
|
|
||||||
navList:[],
|
|
||||||
contentShow:false,
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted(){
|
|
||||||
this.fetchAllList(this.listParams)
|
|
||||||
// this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
},
|
|
||||||
methods:{
|
|
||||||
async fetchAllList(params){
|
|
||||||
this.setLoading('rateLoading', true);
|
|
||||||
const res = await documentsList(params)
|
|
||||||
console.log(res,"res");
|
|
||||||
|
|
||||||
if (res && res.code === 200) {
|
|
||||||
this.navList = res.rows
|
|
||||||
|
|
||||||
if (this.$route.query.id) {
|
|
||||||
this.DetailsParams.id = this.$route.query.id
|
|
||||||
|
|
||||||
}else{
|
|
||||||
this.DetailsParams.id = res.rows[0].id;
|
|
||||||
}
|
|
||||||
if (this.DetailsParams.id) {
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
async fetchProblemDetails(params) {
|
|
||||||
this.setLoading('rateLoading', true);
|
|
||||||
const res = await findDataInfo(params)
|
|
||||||
if(res && res.code === 200){
|
|
||||||
|
|
||||||
this.info = res.data.content || ""
|
|
||||||
this.contentShow = true
|
|
||||||
}
|
|
||||||
this.setLoading('rateLoading', false);
|
|
||||||
},
|
|
||||||
|
|
||||||
backMenu(){
|
|
||||||
this.contentShow = false
|
|
||||||
},
|
|
||||||
|
|
||||||
clickJump(item) {
|
|
||||||
|
|
||||||
this.DetailsParams.id = item.id
|
|
||||||
this.fetchProblemDetails(this.DetailsParams)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="rate">
|
<div class="rate">
|
||||||
<section v-if="$isMobile" class="rateMobile">
|
<section v-if="$isMobile" class="rateMobile">
|
||||||
<!-- <h4>{{$t(`course.rateRelated`)}}</h4>
|
<h4>{{$t(`course.rateRelated`)}}</h4>
|
||||||
<div class="tableBox" >
|
<div class="tableBox" >
|
||||||
<div class="table-title">
|
<div class="table-title">
|
||||||
<span :title="$t(`course.currency`)">{{$t(`course.currency`)}}</span>
|
<span :title="$t(`course.currency`)">{{$t(`course.currency`)}}</span>
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div class="collapseTitle">
|
<div class="collapseTitle">
|
||||||
<span ><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
<span ><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
||||||
<span >{{item.rate}}</span>
|
<span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span>
|
||||||
|
<span v-else>{{item.rate}}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<section class="contentBox2">
|
<section class="contentBox2">
|
||||||
@@ -50,77 +51,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div> -->
|
|
||||||
<section class="leftMenu" v-loading="rateLoading" v-if="!contentShow">
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="item in navList"
|
|
||||||
:class="{ navActive: String(item.id) === String(DetailsParams.id) }"
|
|
||||||
:key="item.id"
|
|
||||||
@click="clickJump(item)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="rightText" v-else>
|
|
||||||
<p class="backMenu" @click="backMenu">{{ $t("apiFile.backMenu") || "返回目录" }} </p>
|
|
||||||
|
|
||||||
<section class="rightContent">
|
|
||||||
<div v-if="rateLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{
|
|
||||||
$t("home.loadingContent") || "正在加载内容..."
|
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-else-if="info && info.trim()"
|
|
||||||
class="dynamic-content"
|
|
||||||
v-html="info"
|
|
||||||
></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t("home.noContent") || "暂无内容" }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="rateBox" v-else>
|
<section class="rateBox" v-else>
|
||||||
<section class="leftMenu">
|
|
||||||
<!-- <ul>
|
|
||||||
<li>{{$t(`course.rateRelated`)}}</li>
|
|
||||||
</ul> -->
|
|
||||||
|
|
||||||
|
<section class="leftMenu">
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li>{{$t(`course.rateRelated`)}}</li>
|
||||||
v-for="item in navList"
|
|
||||||
:class="{ navActive: String(item.id) === String(DetailsParams.id) }"
|
|
||||||
:key="item.id"
|
|
||||||
@click="clickJump(item)"
|
|
||||||
>
|
|
||||||
{{ item.title }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<section class="rightText">
|
<section class="rightText">
|
||||||
<section class="rightContent">
|
<h2>{{$t(`course.rateRelated`)}}</h2>
|
||||||
<div v-if="rateLoading" class="loading-container">
|
|
||||||
<span class="loading-text">{{
|
|
||||||
$t("home.loadingContent") || "正在加载内容..."
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-else-if="info && info.trim()"
|
|
||||||
class="dynamic-content"
|
|
||||||
v-html="info"
|
|
||||||
></div>
|
|
||||||
<div v-else class="no-content">
|
|
||||||
<p>{{ $t("home.noContent") || "暂无内容" }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ----------------------------- -->
|
|
||||||
<!-- <h2>{{$t(`course.rateRelated`)}}</h2>
|
|
||||||
<section class="table">
|
<section class="table">
|
||||||
<div class="tableTitle">
|
<div class="tableTitle">
|
||||||
<span>{{$t(`course.currency`)}}</span>
|
<span>{{$t(`course.currency`)}}</span>
|
||||||
@@ -133,16 +76,20 @@
|
|||||||
<li v-for="item in rateList" :key="item.value">
|
<li v-for="item in rateList" :key="item.value">
|
||||||
<span class="coin"><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
<span class="coin"><img :src="item.img" alt="coin" loading="lazy"> {{item.label}}</span>
|
||||||
<span>{{item.address}}</span>
|
<span>{{item.address}}</span>
|
||||||
<span >{{item.rate}}</span>
|
<span v-if="item.value === 'enx'"> {{ $t(`course.timeLimited`) }} 0%</span>
|
||||||
|
<span v-else>{{item.rate}}</span>
|
||||||
<span>{{item.mode}}</span>
|
<span>{{item.mode}}</span>
|
||||||
<span>{{item.quota}}</span>
|
<span>{{item.quota}}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</section> -->
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -152,119 +99,32 @@ export default {
|
|||||||
metaInfo: {
|
metaInfo: {
|
||||||
meta: [
|
meta: [
|
||||||
{
|
{
|
||||||
name: "keywords",
|
name: 'keywords',
|
||||||
content:
|
content: '费率页面,挖矿费率,收益计算,全网最低费率,Rate Page,Mining Rates,Revenue Calculation,Lowest Rates on the Net'
|
||||||
"费率页面,挖矿费率,收益计算,全网最低费率,Rate Page,Mining Rates,Revenue Calculation,Lowest Rates on the Net",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "description",
|
name: 'description',
|
||||||
content: window.vm.$t(`seo.rate`),
|
content:window.vm.$t(`seo.rate`)
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
],
|
mixins:[IndexJs]
|
||||||
},
|
}
|
||||||
mixins: [IndexJs],
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
||||||
// 手机端适配
|
// 手机端适配
|
||||||
@media screen and (min-width: 220px) and (max-width: 1279px) {
|
@media screen and (min-width: 220px) and (max-width: 1279px) {
|
||||||
|
|
||||||
.rate{
|
.rate{
|
||||||
min-height: 360px !important;
|
min-height: 360px !important;
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
padding-top: 20px !important;
|
padding-top: 20PX !important;
|
||||||
}
|
}
|
||||||
.rateMobile{
|
.rateMobile{
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
.leftMenu ul {
|
|
||||||
margin-top: 30px !important;
|
|
||||||
max-height: 500px !important;
|
|
||||||
overflow-y: auto !important;
|
|
||||||
}
|
}
|
||||||
.leftMenu ul li {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
padding: 10px !important;
|
|
||||||
border-radius: 10px !important;
|
|
||||||
background: rgba(91, 33, 182, 0.06) !important; /* 淡紫块,提高可读性 */
|
|
||||||
border: 1px solid #ede9fe !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
transition: background 0.2s ease, transform 0.1s ease;
|
|
||||||
}
|
|
||||||
.leftMenu ul li:hover {
|
|
||||||
background: rgba(91, 33, 182, 0.12) !important;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.backMenu{
|
|
||||||
position: sticky;
|
|
||||||
top: 8px;
|
|
||||||
z-index: 5;
|
|
||||||
color: #5b21b6;
|
|
||||||
font-size: 0.95rem !important;
|
|
||||||
margin: 0 0 10px 2px !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
background: rgba(255,255,255,0.9);
|
|
||||||
border: 1px solid #ede9fe;
|
|
||||||
padding: 6px 10px;
|
|
||||||
border-radius: 999px;
|
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content {
|
|
||||||
overflow-x: auto !important; /* 超出时允许横向滚动(兜底) */
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(table) {
|
|
||||||
/* 对含有 colspan/rowspan 的表格,固定布局会引发表头与列错位,这里改为自动布局 */
|
|
||||||
table-layout: auto !important;
|
|
||||||
width: 100% !important;
|
|
||||||
border-collapse: collapse !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(th),
|
|
||||||
.rightContent .dynamic-content :deep(td) {
|
|
||||||
// word-break: break-word !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
padding: 2px !important;
|
|
||||||
font-size: 0.7rem !important; /* 表格单元格字号 */
|
|
||||||
min-width: 0 !important; /* 覆盖外层全局 td 的最小宽度,避免小屏列被强撑导致错位 */
|
|
||||||
vertical-align: left !important;
|
|
||||||
}
|
|
||||||
/* 步骤里的段落在移动端必须自动换行,禁止引发横向滚动条 */
|
|
||||||
.rightContent .dynamic-content :deep(p) {
|
|
||||||
max-width: 100% !important;
|
|
||||||
white-space: normal !important;
|
|
||||||
word-break: break-word !important; /* 优先按单词/字符断行 */
|
|
||||||
overflow-wrap: anywhere !important; /* 极端长串也强制换行 */
|
|
||||||
word-wrap: break-word !important; /* 旧版兼容 */
|
|
||||||
font-size: 0.8rem !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(a) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(li) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(pre) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(font) {
|
|
||||||
font-size: 0.7rem !important;
|
|
||||||
min-width: 40px !important;
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
.rightContent .dynamic-content :deep(h2) {
|
|
||||||
font-size: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rightContent .dynamic-content :deep(h3) {
|
|
||||||
font-size: 0.9rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
h4{
|
h4{
|
||||||
color: rgba(0,0,0,0.8);
|
color: rgba(0,0,0,0.8);
|
||||||
padding-left: 5%;
|
padding-left: 5%;
|
||||||
@@ -282,7 +142,7 @@ export default {
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
.table-title{
|
.table-title{
|
||||||
height: 50px;
|
height: 50px;
|
||||||
background: #d2c4e8;
|
background: #D2C4E8;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -322,12 +182,15 @@ export default {
|
|||||||
span:nth-of-type(2){
|
span:nth-of-type(2){
|
||||||
width:60% !important;
|
width:60% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-collapse-item__wrap{
|
::v-deep .el-collapse-item__wrap{
|
||||||
background: #f0e9f5;
|
background: #F0E9F5;
|
||||||
}
|
}
|
||||||
.belowTable{
|
.belowTable{
|
||||||
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
@@ -340,17 +203,21 @@ export default {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.paginationBox{
|
.paginationBox{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.rate{
|
.rate{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 600px;
|
min-height: 600PX;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
background-image: url(../../assets/img/miningAccount/top.png);
|
background-image: url(../../assets/img/miningAccount/top.png);
|
||||||
background-size: 100% 50%;
|
background-size: 100% 50%;
|
||||||
@@ -358,58 +225,54 @@ export default {
|
|||||||
background-position: 30% -15%;
|
background-position: 30% -15%;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-top: 60px;
|
padding-top: 60PX;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
.rateBox{
|
.rateBox{
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
min-height: 700px;
|
min-height: 700PX;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8PX;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 20px;
|
padding: 20PX;
|
||||||
transition: 0.3s linear;
|
transition: 0.3S linear;
|
||||||
|
|
||||||
.leftMenu{
|
.leftMenu{
|
||||||
width: 18%;
|
width: 18%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-right: 2%;
|
margin-right: 2%;
|
||||||
padding-top: 50px;
|
padding-top: 50PX;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 0px 0px 5px 2px #ccc;
|
box-shadow: 0px 0px 5px 2px #ccc;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
ul{
|
ul{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
li{
|
li{
|
||||||
width: 100%;
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
min-height: 40px;
|
min-height: 40PX;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 10px;
|
margin-top: 10PX;
|
||||||
border-radius: 5px;
|
border-radius: 5PX;
|
||||||
background: rgba(210,195,234,0.3);
|
background: rgba(210,195,234,0.3);
|
||||||
|
|
||||||
width: 90%;
|
width: 90%;
|
||||||
padding:8px 8px;
|
padding:8px 8px;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
background: #d2c3ea;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.rightText{
|
.rightText{
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
@@ -419,8 +282,6 @@ export default {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top:30px;
|
padding-top:30px;
|
||||||
background: #fff;
|
|
||||||
padding: 20px;
|
|
||||||
h2{
|
h2{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 50px;
|
padding-left: 50px;
|
||||||
@@ -440,8 +301,8 @@ export default {
|
|||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 60px;
|
height: 60PX;
|
||||||
background: #d2c3ea;
|
background: #D2C3EA;
|
||||||
border-radius: 5px 5px 0px 0px;
|
border-radius: 5px 5px 0px 0px;
|
||||||
span{
|
span{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -463,9 +324,9 @@ export default {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 50px;
|
height: 50PX;
|
||||||
background: #f8f8fa;
|
background: #F8F8FA;
|
||||||
margin-top: 8px;
|
margin-top: 8PX;
|
||||||
font-size: 0.95rem;
|
font-size: 0.95rem;
|
||||||
span{
|
span{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -487,55 +348,9 @@ export default {
|
|||||||
// li:nth-child(even) {
|
// li:nth-child(even) {
|
||||||
// background-color: #ffff; /* 甚至可以是你想要的任何颜色 */
|
// background-color: #ffff; /* 甚至可以是你想要的任何颜色 */
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dynamic-content {
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.7;
|
|
||||||
color: #222;
|
|
||||||
// 富文本样式
|
|
||||||
:deep(table) {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(th),
|
|
||||||
:deep(td) {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 8px 8px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
:deep(th) {
|
|
||||||
background: #d2c3ea;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
:deep(strong),
|
|
||||||
:deep(b) {
|
|
||||||
font-weight: bold !important;
|
|
||||||
color: inherit !important;
|
|
||||||
font-style: normal !important;
|
|
||||||
}
|
|
||||||
:deep(em),
|
|
||||||
:deep(i) {
|
|
||||||
font-style: italic !important;
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
:deep(a) {
|
|
||||||
color: #661ffb !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navActive {
|
|
||||||
background: #ac85e0 !important;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -1228,8 +1228,6 @@ export default {
|
|||||||
this.getMinerAccountPowerData(this.PowerParams)
|
this.getMinerAccountPowerData(this.PowerParams)
|
||||||
this.getAccountPowerDistributionData(this.PowerDistribution)
|
this.getAccountPowerDistributionData(this.PowerDistribution)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"$i18n.locale":(val)=>{
|
"$i18n.locale":(val)=>{
|
||||||
location.reload();//刷新页面 刷新echarts
|
location.reload();//刷新页面 刷新echarts
|
||||||
@@ -1273,12 +1271,6 @@ export default {
|
|||||||
this.getAccountPowerDistributionData(this.PowerDistribution)
|
this.getAccountPowerDistributionData(this.PowerDistribution)
|
||||||
|
|
||||||
|
|
||||||
this.registerRecoveryMethod('getMinerListData', this.MinerListParams);
|
|
||||||
this.registerRecoveryMethod('getMinerAccountPowerData', this.PowerParams);
|
|
||||||
this.registerRecoveryMethod('getAccountPowerDistributionData', this.PowerDistribution);
|
|
||||||
this.registerRecoveryMethod('fetchPageInfo', {key:this.params.key});
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
@@ -1328,7 +1320,7 @@ export default {
|
|||||||
},
|
},
|
||||||
//返回权限 1矿工 2收益 3支付
|
//返回权限 1矿工 2收益 3支付
|
||||||
async fetchPageInfo(params){
|
async fetchPageInfo(params){
|
||||||
this.setLoading('jurisdictionLoading', true);
|
this.jurisdictionLoading = true
|
||||||
const data = await getPageInfo(params)
|
const data = await getPageInfo(params)
|
||||||
console.log(data);
|
console.log(data);
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
@@ -1362,7 +1354,7 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('jurisdictionLoading', false);
|
this.jurisdictionLoading = false
|
||||||
},
|
},
|
||||||
//获取当前挖矿账号信息(包含收益、余额)
|
//获取当前挖矿账号信息(包含收益、余额)
|
||||||
async getMinerAccountInfoData(params) {
|
async getMinerAccountInfoData(params) {
|
||||||
@@ -1370,11 +1362,11 @@ export default {
|
|||||||
this.MinerAccountData = data.data
|
this.MinerAccountData = data.data
|
||||||
},
|
},
|
||||||
async getMinerAccountPowerData(params) {
|
async getMinerAccountPowerData(params) {
|
||||||
this.setLoading('powerChartLoading', true);
|
this.powerChartLoading = true
|
||||||
const data = await getMinerAccountPower(params)
|
const data = await getMinerAccountPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('powerChartLoading', false);
|
this.powerChartLoading = false
|
||||||
if (this.myChart) {
|
if (this.myChart) {
|
||||||
this.myChart.dispose()//销毁图表实列
|
this.myChart.dispose()//销毁图表实列
|
||||||
}
|
}
|
||||||
@@ -1407,13 +1399,13 @@ export default {
|
|||||||
this.option.series[1].data = rejectRate
|
this.option.series[1].data = rejectRate
|
||||||
|
|
||||||
this.inCharts()
|
this.inCharts()
|
||||||
this.setLoading('powerChartLoading', false);
|
this.powerChartLoading = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
async getAccountPowerDistributionData(params) {
|
async getAccountPowerDistributionData(params) {
|
||||||
this.setLoading('barChartLoading', true);
|
this.barChartLoading = true
|
||||||
const data = await getAccountPowerDistribution(params)
|
const data = await getAccountPowerDistribution(params)
|
||||||
let barData = data.data
|
let barData = data.data
|
||||||
let xData = []
|
let xData = []
|
||||||
@@ -1425,7 +1417,7 @@ export default {
|
|||||||
this.barOption.xAxis[0].data = xData
|
this.barOption.xAxis[0].data = xData
|
||||||
this.barOption.series[0].data = barValueList
|
this.barOption.series[0].data = barValueList
|
||||||
this.barInCharts()
|
this.barInCharts()
|
||||||
this.setLoading('barChartLoading', false);
|
this.barChartLoading = false
|
||||||
},
|
},
|
||||||
formatNumber(num) {//保留两位小数并补0
|
formatNumber(num) {//保留两位小数并补0
|
||||||
const intPart = Math.floor(num);
|
const intPart = Math.floor(num);
|
||||||
@@ -1433,7 +1425,7 @@ export default {
|
|||||||
return `${intPart}.${String(decimalPart).padStart(2, '0')}`;
|
return `${intPart}.${String(decimalPart).padStart(2, '0')}`;
|
||||||
},
|
},
|
||||||
async getMinerListData(params) {
|
async getMinerListData(params) {
|
||||||
this.setLoading('MinerListLoading', true);
|
this.MinerListLoading = true
|
||||||
const data = await getMinerList(params)
|
const data = await getMinerList(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.MinerListData = data.data
|
this.MinerListData = data.data
|
||||||
@@ -1459,17 +1451,17 @@ export default {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLoading('MinerListLoading', false);
|
this.MinerListLoading = false
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//小图
|
//小图
|
||||||
async getMinerPowerData(params) {
|
async getMinerPowerData(params) {
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1515,15 +1507,15 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
},
|
},
|
||||||
//小图
|
//小图
|
||||||
async getMinerPowerOnLine(params) {
|
async getMinerPowerOnLine(params) {
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1564,14 +1556,14 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
},
|
},
|
||||||
//小图
|
//小图
|
||||||
async getMinerPowerOffLine(params) {
|
async getMinerPowerOffLine(params) {
|
||||||
this.setLoading('miniLoading', true);
|
this.miniLoading=true
|
||||||
const data = await getMinerPower(params)
|
const data = await getMinerPower(params)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let miniData = data.data
|
let miniData = data.data
|
||||||
@@ -1613,7 +1605,7 @@ export default {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('miniLoading', false);
|
this.miniLoading=false
|
||||||
},
|
},
|
||||||
async getHistoryIncomeData(params) {
|
async getHistoryIncomeData(params) {
|
||||||
const data = await getHistoryIncome(params)
|
const data = await getHistoryIncome(params)
|
||||||
@@ -1921,12 +1913,6 @@ export default {
|
|||||||
case `alph`:
|
case `alph`:
|
||||||
window.open(`https://explorer.alephium.org/transactions/${txid}`)
|
window.open(`https://explorer.alephium.org/transactions/${txid}`)
|
||||||
break;
|
break;
|
||||||
case `xmr`:
|
|
||||||
window.open(`https://localmonero.co/blocks/tx/${txid}`)
|
|
||||||
break;
|
|
||||||
case `sha3x`:
|
|
||||||
window.open(`https://explore.tari.com/txs/${txid}`)
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
type="email"
|
type="email"
|
||||||
prefix-icon="el-icon-message"
|
prefix-icon="el-icon-message"
|
||||||
v-model="registerForm.email"
|
v-model="registerForm.email"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.Account`)"
|
:placeholder="$t(`user.Account`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -41,7 +40,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="registerForm.emailCode"
|
v-model="registerForm.emailCode"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -61,7 +59,6 @@
|
|||||||
:title="$t(`user.passwordPrompt`)"
|
:title="$t(`user.passwordPrompt`)"
|
||||||
type="password"
|
type="password"
|
||||||
v-model="registerForm.password"
|
v-model="registerForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.password`)"
|
:placeholder="$t(`user.password`)"
|
||||||
@@ -76,7 +73,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="registerForm.confirmPassword"
|
v-model="registerForm.confirmPassword"
|
||||||
@input="handleConfirmPasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.confirmPassword`)"
|
:placeholder="$t(`user.confirmPassword`)"
|
||||||
@@ -148,7 +144,6 @@
|
|||||||
type="email"
|
type="email"
|
||||||
prefix-icon="el-icon-message"
|
prefix-icon="el-icon-message"
|
||||||
v-model="registerForm.email"
|
v-model="registerForm.email"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.Account`)"
|
:placeholder="$t(`user.Account`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -159,7 +154,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="registerForm.emailCode"
|
v-model="registerForm.emailCode"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -179,7 +173,6 @@
|
|||||||
:title="$t(`user.passwordPrompt`)"
|
:title="$t(`user.passwordPrompt`)"
|
||||||
type="password"
|
type="password"
|
||||||
v-model="registerForm.password"
|
v-model="registerForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.password`)"
|
:placeholder="$t(`user.password`)"
|
||||||
@@ -194,7 +187,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="registerForm.confirmPassword"
|
v-model="registerForm.confirmPassword"
|
||||||
@input="handleConfirmPasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.confirmPassword`)"
|
:placeholder="$t(`user.confirmPassword`)"
|
||||||
@@ -241,7 +233,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getRegister, getRegisterCode } from "../../api/login";
|
import { getRegister, getRegisterCode } from "../../api/login";
|
||||||
import { encryption } from "../../utils/fun";
|
import { encryption } from "../../utils/fun";
|
||||||
import { validatePassword, formatPasswordErrors } from "../../utils/passwordValidator";
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
// const equalToPassword = (rule, value, callback) => {
|
// const equalToPassword = (rule, value, callback) => {
|
||||||
@@ -342,44 +333,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to) {
|
|
||||||
// 路由变化时自动同步语言和radio
|
|
||||||
const match = to.path.match(/^\/(zh|en)(\/|$)/);
|
|
||||||
if (match) {
|
|
||||||
this.radio = match[1];
|
|
||||||
this.lang = match[1];
|
|
||||||
this.$i18n.locale = match[1];
|
|
||||||
localStorage.setItem("lang", match[1]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$i18n.locale": function () {
|
"$i18n.locale": function () {
|
||||||
this.translate();
|
this.translate();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// this.lang = this.$i18n.locale;
|
this.lang = this.$i18n.locale;
|
||||||
// this.radio = localStorage.getItem("lang")
|
this.radio = localStorage.getItem("lang")
|
||||||
// ? localStorage.getItem("lang")
|
? localStorage.getItem("lang")
|
||||||
// : "en";
|
: "en";
|
||||||
|
|
||||||
// 获取当前路由路径
|
|
||||||
const path = this.$route.path;
|
|
||||||
// 匹配 /zh/ 或 /en/ 作为语言前缀
|
|
||||||
const match = path.match(/^\/(zh|en)(\/|$)/);
|
|
||||||
if (match) {
|
|
||||||
this.radio = match[1];
|
|
||||||
this.lang = match[1];
|
|
||||||
this.$i18n.locale = match[1];
|
|
||||||
localStorage.setItem("lang", match[1]);
|
|
||||||
} else {
|
|
||||||
// fallback 到 localStorage 或 "en"
|
|
||||||
this.radio = localStorage.getItem("lang") || "en";
|
|
||||||
this.lang = this.radio;
|
|
||||||
this.$i18n.locale = this.radio;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (const key in this.registerForm) {
|
for (const key in this.registerForm) {
|
||||||
this.registerForm[key] = "";
|
this.registerForm[key] = "";
|
||||||
}
|
}
|
||||||
@@ -583,15 +545,18 @@ const path = this.$route.path;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码验证 - 使用优化后的详细校验逻辑
|
// 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*)
|
||||||
const validation = validatePassword(this.registerForm.password);
|
// const regexPassword =
|
||||||
if (!validation.valid) {
|
// /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
||||||
// 生成友好的逐项错误提示
|
const regexPassword =
|
||||||
const errorMessage = formatPasswordErrors(validation.errors, this.$t.bind(this));
|
/^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/;
|
||||||
|
const PasswordIsValid = regexPassword.test(
|
||||||
|
this.registerForm.password
|
||||||
|
);
|
||||||
|
if (!PasswordIsValid) {
|
||||||
this.$message({
|
this.$message({
|
||||||
message: errorMessage,
|
message: this.$t(`user.passwordFormat`),
|
||||||
type: "error",
|
type: "error",
|
||||||
duration: 5000, // 延长显示时间,因为错误信息可能有多条
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -634,45 +599,6 @@ const path = this.$route.path;
|
|||||||
handleClick() {
|
handleClick() {
|
||||||
this.$router.push(`/${this.lang}`);
|
this.$router.push(`/${this.lang}`);
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 去除输入值中的空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @returns {string} 去除空格后的值
|
|
||||||
*/
|
|
||||||
removeSpaces(value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return value.replace(/\s/g, '');
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理邮箱输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleEmailInput(value) {
|
|
||||||
this.registerForm.email = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理验证码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleCodeInput(value) {
|
|
||||||
this.registerForm.emailCode = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handlePasswordInput(value) {
|
|
||||||
this.registerForm.password = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理确认密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleConfirmPasswordInput(value) {
|
|
||||||
this.registerForm.confirmPassword = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -235,10 +235,6 @@ export default {
|
|||||||
|
|
||||||
this.getLuckData(this.params)
|
this.getLuckData(this.params)
|
||||||
this.getBlockInfoData(this.BlockInfoParams)
|
this.getBlockInfoData(this.BlockInfoParams)
|
||||||
|
|
||||||
this.registerRecoveryMethod('getLuckData', this.params);
|
|
||||||
this.registerRecoveryMethod('getBlockInfoData', this.BlockInfoParams);
|
|
||||||
|
|
||||||
let value = localStorage.getItem("activeItemCoin")
|
let value = localStorage.getItem("activeItemCoin")
|
||||||
this.activeItemCoin = JSON.parse(value)
|
this.activeItemCoin = JSON.parse(value)
|
||||||
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
this.currencyList = JSON.parse(localStorage.getItem("currencyList"))
|
||||||
@@ -264,14 +260,14 @@ export default {
|
|||||||
// },
|
// },
|
||||||
|
|
||||||
getLuckData: Debounce(async function (params) {
|
getLuckData: Debounce(async function (params) {
|
||||||
this.setLoading('LuckDataLoading', true);
|
this.LuckDataLoading = true
|
||||||
const data = await getLuck(params)
|
const data = await getLuck(params)
|
||||||
if (data && data.code == 200) {
|
if (data && data.code == 200) {
|
||||||
this.luckData = data.data
|
this.luckData = data.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.setLoading('LuckDataLoading', false);
|
this.LuckDataLoading = false
|
||||||
}, 200),
|
}, 200),
|
||||||
// async getBlockInfoData(params) {
|
// async getBlockInfoData(params) {
|
||||||
// this.reportBlockLoading=true
|
// this.reportBlockLoading=true
|
||||||
@@ -290,10 +286,10 @@ export default {
|
|||||||
// },
|
// },
|
||||||
getBlockInfoData: Debounce(async function (params) {
|
getBlockInfoData: Debounce(async function (params) {
|
||||||
|
|
||||||
this.setLoading('reportBlockLoading', true);
|
this.reportBlockLoading = true
|
||||||
const data = await getBlockInfo(params)
|
const data = await getBlockInfo(params)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
this.setLoading('reportBlockLoading', false);
|
this.reportBlockLoading = false
|
||||||
}
|
}
|
||||||
this.totalSize = data.total
|
this.totalSize = data.total
|
||||||
this.BlockInfoData = data.rows
|
this.BlockInfoData = data.rows
|
||||||
@@ -302,7 +298,7 @@ export default {
|
|||||||
})
|
})
|
||||||
// this.currentPage = 1
|
// this.currentPage = 1
|
||||||
// console.log(data,"获取币种信息");
|
// console.log(data,"获取币种信息");
|
||||||
this.setLoading('reportBlockLoading', false);
|
this.reportBlockLoading = false
|
||||||
|
|
||||||
}, 200),
|
}, 200),
|
||||||
handleActiveItemChange(item) {
|
handleActiveItemChange(item) {
|
||||||
@@ -318,9 +314,6 @@ export default {
|
|||||||
clickCurrency(item) {
|
clickCurrency(item) {
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
// 设置标记,防止触发 watch
|
// 设置标记,防止触发 watch
|
||||||
|
|
||||||
this.luckData = {}
|
|
||||||
|
|
||||||
this.isInternalChange = true;
|
this.isInternalChange = true;
|
||||||
this.activeItemCoin = item;
|
this.activeItemCoin = item;
|
||||||
this.$addStorageEvent(1, `activeItemCoin`, JSON.stringify(item))
|
this.$addStorageEvent(1, `activeItemCoin`, JSON.stringify(item))
|
||||||
@@ -355,13 +348,6 @@ export default {
|
|||||||
case `alph`:
|
case `alph`:
|
||||||
window.open(`https://explorer.alephium.org/blocks/${item.hash}`)
|
window.open(`https://explorer.alephium.org/blocks/${item.hash}`)
|
||||||
break;
|
break;
|
||||||
case `xmr`:
|
|
||||||
window.open(`https://localmonero.co/blocks/block/${item.height}`)
|
|
||||||
break;
|
|
||||||
case `sha3x`:
|
|
||||||
window.open(`https://explore.tari.com/blocks/${item.height}`)
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</el-menu>
|
</el-menu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="luckyBox" v-show="this.activeItemCoin.value != 'enx' && this.activeItemCoin.value != 'alph'">
|
<div class="luckyBox" >
|
||||||
|
|
||||||
<div class="luckyItem">
|
<div class="luckyItem">
|
||||||
<span class="title">{{$t(`home.lucky3`)}}</span>
|
<span class="title">{{$t(`home.lucky3`)}}</span>
|
||||||
@@ -113,7 +113,6 @@
|
|||||||
v-for="item in currencyList"
|
v-for="item in currencyList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
@click="clickCurrency(item)"
|
@click="clickCurrency(item)"
|
||||||
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="currency-logo lazy lazy-coin-logo"
|
class="currency-logo lazy lazy-coin-logo"
|
||||||
@@ -126,8 +125,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<!-- v-loading = "LuckDataLoading" -->
|
<!-- v-loading = "LuckDataLoading" -->
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
|
||||||
|
<div class="luckyBox" >
|
||||||
<div class="luckyBox" v-show="this.activeItemCoin.value != 'enx' && this.activeItemCoin.value != 'alph' && this.activeItemCoin.value != 'monero'" >
|
|
||||||
|
|
||||||
<div class="luckyItem">
|
<div class="luckyItem">
|
||||||
<span class="title">{{$t(`home.lucky3`)}}</span>
|
<span class="title">{{$t(`home.lucky3`)}}</span>
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
prefix-icon="el-icon-user"
|
prefix-icon="el-icon-user"
|
||||||
v-model="loginForm.email"
|
v-model="loginForm.email"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t('user.Account')"
|
:placeholder="$t('user.Account')"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -40,7 +39,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="loginForm.resetPwdCode"
|
v-model="loginForm.resetPwdCode"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -60,7 +58,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
@@ -74,13 +71,11 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.newPassword"
|
v-model="loginForm.newPassword"
|
||||||
@input="handleNewPasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
:placeholder="$t('user.newPassword')"
|
:placeholder="$t('user.newPassword')"
|
||||||
></el-input>
|
></el-input>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item prop="gCode" v-if="isItBound">
|
<!-- <el-form-item prop="gCode" v-if="isItBound">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -155,7 +150,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
prefix-icon="el-icon-user"
|
prefix-icon="el-icon-user"
|
||||||
v-model="loginForm.email"
|
v-model="loginForm.email"
|
||||||
@input="handleEmailInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t('user.Account')"
|
:placeholder="$t('user.Account')"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -166,7 +160,6 @@
|
|||||||
type="text"
|
type="text"
|
||||||
prefix-icon="el-icon-chat-line-square"
|
prefix-icon="el-icon-chat-line-square"
|
||||||
v-model="loginForm.resetPwdCode"
|
v-model="loginForm.resetPwdCode"
|
||||||
@input="handleCodeInput($event)"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:placeholder="$t(`user.verificationCode`)"
|
:placeholder="$t(`user.verificationCode`)"
|
||||||
></el-input>
|
></el-input>
|
||||||
@@ -186,7 +179,6 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.password"
|
v-model="loginForm.password"
|
||||||
@input="handlePasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
@@ -200,13 +192,11 @@
|
|||||||
<el-input
|
<el-input
|
||||||
type="password"
|
type="password"
|
||||||
v-model="loginForm.newPassword"
|
v-model="loginForm.newPassword"
|
||||||
@input="handleNewPasswordInput($event)"
|
|
||||||
prefix-icon="el-icon-unlock"
|
prefix-icon="el-icon-unlock"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
showPassword
|
showPassword
|
||||||
:placeholder="$t('user.newPassword')"
|
:placeholder="$t('user.newPassword')"
|
||||||
></el-input>
|
></el-input>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item prop="gCode" v-if="isItBound">
|
<!-- <el-form-item prop="gCode" v-if="isItBound">
|
||||||
<el-input
|
<el-input
|
||||||
@@ -257,8 +247,7 @@
|
|||||||
import { getResetPwd, getResetPwdCode } from "../../api/login";
|
import { getResetPwd, getResetPwdCode } from "../../api/login";
|
||||||
import { encryption } from "../../utils/fun";
|
import { encryption } from "../../utils/fun";
|
||||||
import { getEmailIfBind } from "../../api/personalCenter";
|
import { getEmailIfBind } from "../../api/personalCenter";
|
||||||
import { Debounce,throttle }from "../../utils/publicMethods";
|
|
||||||
import { validatePassword, formatPasswordErrors } from "../../utils/passwordValidator";
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -430,10 +419,6 @@ export default {
|
|||||||
type: "success",
|
type: "success",
|
||||||
showClose: true,
|
showClose: true,
|
||||||
});
|
});
|
||||||
for (const key in this.loginForm) {//清空表单
|
|
||||||
this.loginForm[key] = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$router.push(`/${this.lang}/login`);
|
this.$router.push(`/${this.lang}/login`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -536,8 +521,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
submitForm() {
|
||||||
submitForm:Debounce(function(){
|
|
||||||
this.$refs.ruleForm.validate((valid) => {
|
this.$refs.ruleForm.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
//去空格
|
//去空格
|
||||||
@@ -584,16 +568,16 @@ export default {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 密码验证 - 使用优化后的详细校验逻辑
|
// 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*)
|
||||||
const validation = validatePassword(this.loginForm.password);
|
const regexPassword =
|
||||||
if (!validation.valid) {
|
/^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
||||||
// 生成友好的逐项错误提示
|
const PasswordIsValid = regexPassword.test(this.loginForm.password);
|
||||||
const errorMessage = formatPasswordErrors(validation.errors, this.$t.bind(this));
|
if (!PasswordIsValid) {
|
||||||
|
// 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
||||||
this.$message({
|
this.$message({
|
||||||
message: errorMessage,
|
message: this.$t(`user.PasswordReminder`),
|
||||||
type: "error",
|
type: "error",
|
||||||
showClose: true,
|
showClose: true,
|
||||||
duration: 5000, // 延长显示时间,因为错误信息可能有多条
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -612,125 +596,10 @@ export default {
|
|||||||
this.fetchResetPwd(form);
|
this.fetchResetPwd(form);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},200),
|
},
|
||||||
// submitForm() {
|
|
||||||
// this.$refs.ruleForm.validate((valid) => {
|
|
||||||
// if (valid) {
|
|
||||||
// //去空格
|
|
||||||
// this.loginForm.userName = this.loginForm.email.trim();
|
|
||||||
// this.loginForm.password = this.loginForm.password.trim();
|
|
||||||
// this.loginForm.newPassword = this.loginForm.newPassword.trim();
|
|
||||||
// if (this.loginForm.password !== this.loginForm.newPassword) {
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`user.confirmPassword2`),
|
|
||||||
// type: "error",
|
|
||||||
// customClass: "messageClass",
|
|
||||||
// showClose: true,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// //邮箱格式验证
|
|
||||||
// const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
|
|
||||||
|
|
||||||
// let isMailbox = emailRegex.test(this.loginForm.email);
|
|
||||||
// if (!isMailbox) {
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`user.emailVerification`),
|
|
||||||
// type: "error",
|
|
||||||
// customClass: "messageClass",
|
|
||||||
// showClose: true,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// //用户名规则1.长度限制:3<=用户名<=16; 字符限制:仅允许使用字母、数字、下划线 用户名必须以字母开头
|
|
||||||
// // const regex = /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/; // 正则表达式
|
|
||||||
// // const isValid = regex.test(this.loginForm.email);
|
|
||||||
// // if (!isValid) {
|
|
||||||
// // // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
|
||||||
// // this.$message({
|
|
||||||
// // message: this.$t(`user.accountReminder`),
|
|
||||||
// // type: "error",
|
|
||||||
// // customClass: "messageClass",
|
|
||||||
// // showClose: true
|
|
||||||
// // });
|
|
||||||
|
|
||||||
// // return;
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 密码验证 8<=密码<=32 包含大小写字母、数字和特殊字符(!@#¥%……&*)
|
|
||||||
// const regexPassword =
|
|
||||||
// /^(?!.*[\u4e00-\u9fa5])(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_]+$)(?![a-z0-9]+$)(?![a-z\W_]+$)(?![0-9\W_]+$)[a-zA-Z0-9\W_]{8,32}$/; // 正则表达式
|
|
||||||
// const PasswordIsValid = regexPassword.test(this.loginForm.password);
|
|
||||||
// if (!PasswordIsValid) {
|
|
||||||
// // 如果输入不符合要求,可以根据具体需求给出错误提示或进行其他处理
|
|
||||||
// this.$message({
|
|
||||||
// message: this.$t(`user.PasswordReminder`),
|
|
||||||
// type: "error",
|
|
||||||
// showClose: true,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // ,gCode: this.loginForm.gCode,
|
|
||||||
// let obj = {
|
|
||||||
// email: this.loginForm.email,
|
|
||||||
// password: this.loginForm.password,
|
|
||||||
// resetPwdCode: this.loginForm.resetPwdCode,
|
|
||||||
// };
|
|
||||||
// //加密
|
|
||||||
// // const form = { ...this.loginForm };
|
|
||||||
// // form.password = encryption(this.loginForm.password);
|
|
||||||
// const form = { ...obj };
|
|
||||||
// form.password = encryption(obj.password);
|
|
||||||
// this.fetchResetPwd(form);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
handleClick() {
|
handleClick() {
|
||||||
this.$router.push(`/${this.lang}`);
|
this.$router.push(`/${this.lang}`);
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 去除输入值中的空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
* @returns {string} 去除空格后的值
|
|
||||||
*/
|
|
||||||
removeSpaces(value) {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return value.replace(/\s/g, '');
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理邮箱输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleEmailInput(value) {
|
|
||||||
this.loginForm.email = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理验证码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleCodeInput(value) {
|
|
||||||
this.loginForm.resetPwdCode = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handlePasswordInput(value) {
|
|
||||||
this.loginForm.password = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 处理新密码输入,自动去除空格
|
|
||||||
* @param {string} value - 输入值
|
|
||||||
*/
|
|
||||||
handleNewPasswordInput(value) {
|
|
||||||
this.loginForm.newPassword = this.removeSpaces(value);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user