v1.2.0需求开发中

This commit is contained in:
yaoqin 2025-07-18 16:22:28 +08:00
parent a0ebd8254a
commit 9fa026f267
75 changed files with 10703 additions and 1197 deletions

View File

@ -1139,7 +1139,6 @@
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
"integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.14.0"
},
@ -1147,8 +1146,7 @@
"regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
}
}
},
@ -1755,6 +1753,16 @@
"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=="
},
"@transloadit/prettier-bytes": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz",
"integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA=="
},
"@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
@ -1825,6 +1833,11 @@
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true
},
"@types/event-emitter": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.5.tgz",
"integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ=="
},
"@types/express": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
@ -2007,6 +2020,53 @@
"@types/node": "*"
}
},
"@uppy/companion-client": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz",
"integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==",
"requires": {
"@uppy/utils": "^4.1.2",
"namespace-emitter": "^2.0.1"
}
},
"@uppy/core": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz",
"integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
"requires": {
"@transloadit/prettier-bytes": "0.0.7",
"@uppy/store-default": "^2.1.1",
"@uppy/utils": "^4.1.3",
"lodash.throttle": "^4.1.1",
"mime-match": "^1.0.2",
"namespace-emitter": "^2.0.1",
"nanoid": "^3.1.25",
"preact": "^10.5.13"
}
},
"@uppy/store-default": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz",
"integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ=="
},
"@uppy/utils": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz",
"integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==",
"requires": {
"lodash.throttle": "^4.1.1"
}
},
"@uppy/xhr-upload": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
"integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
"requires": {
"@uppy/companion-client": "^2.2.2",
"@uppy/utils": "^4.1.2",
"nanoid": "^3.1.25"
}
},
"@vue/babel-helper-vue-jsx-merge-props": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
@ -2629,6 +2689,88 @@
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
"dev": true
},
"@wangeditor/basic-modules": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
"integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
"requires": {
"is-url": "^1.2.4"
}
},
"@wangeditor/code-highlight": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz",
"integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==",
"requires": {
"prismjs": "^1.23.0"
}
},
"@wangeditor/core": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.19.tgz",
"integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
"requires": {
"@types/event-emitter": "^0.3.3",
"event-emitter": "^0.3.5",
"html-void-elements": "^2.0.0",
"i18next": "^20.4.0",
"scroll-into-view-if-needed": "^2.2.28",
"slate-history": "^0.66.0"
}
},
"@wangeditor/editor": {
"version": "5.1.23",
"resolved": "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.23.tgz",
"integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
"requires": {
"@uppy/core": "^2.1.1",
"@uppy/xhr-upload": "^2.0.3",
"@wangeditor/basic-modules": "^1.1.7",
"@wangeditor/code-highlight": "^1.0.3",
"@wangeditor/core": "^1.1.19",
"@wangeditor/list-module": "^1.0.5",
"@wangeditor/table-module": "^1.1.4",
"@wangeditor/upload-image-module": "^1.0.2",
"@wangeditor/video-module": "^1.1.4",
"dom7": "^3.0.0",
"is-hotkey": "^0.2.0",
"lodash.camelcase": "^4.3.0",
"lodash.clonedeep": "^4.5.0",
"lodash.debounce": "^4.0.8",
"lodash.foreach": "^4.5.0",
"lodash.isequal": "^4.5.0",
"lodash.throttle": "^4.1.1",
"lodash.toarray": "^4.4.0",
"nanoid": "^3.2.0",
"slate": "^0.72.0",
"snabbdom": "^3.1.0"
}
},
"@wangeditor/editor-for-vue": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-1.0.2.tgz",
"integrity": "sha512-BOENvAXJVtVXlE2X50AAvjV82YlCUeu5cbeR0cvEQHQjYtiVnJtq7HSoj85r2kTgGouI5OrpJG9BBEjSjUSPyA=="
},
"@wangeditor/list-module": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz",
"integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ=="
},
"@wangeditor/table-module": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz",
"integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w=="
},
"@wangeditor/upload-image-module": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz",
"integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA=="
},
"@wangeditor/video-module": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@wangeditor/video-module/-/video-module-1.1.4.tgz",
"integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg=="
},
"@webassemblyjs/ast": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
@ -3447,7 +3589,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dev": true,
"requires": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
@ -3899,6 +4040,11 @@
}
}
},
"compute-scroll-into-view": {
"version": "1.0.20",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
"integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -4264,6 +4410,15 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"d": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
"requires": {
"es5-ext": "^0.10.64",
"type": "^2.7.2"
}
},
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@ -4289,6 +4444,19 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
"integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="
},
"deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"requires": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
}
},
"deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@ -4403,7 +4571,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"requires": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -4420,7 +4587,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dev": true,
"requires": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
@ -4530,6 +4696,14 @@
}
}
},
"dom7": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/dom7/-/dom7-3.0.0.tgz",
"integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
"requires": {
"ssr-window": "^3.0.0-alpha.1"
}
},
"domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
@ -4786,6 +4960,27 @@
"hasown": "^2.0.2"
}
},
"es5-ext": {
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
"requires": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"esniff": "^2.0.1",
"next-tick": "^1.1.0"
}
},
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"es6-promise": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
@ -4799,6 +4994,15 @@
"es6-promise": "^4.0.3"
}
},
"es6-symbol": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
"requires": {
"d": "^1.0.2",
"ext": "^1.7.0"
}
},
"escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@ -5197,6 +5401,17 @@
}
}
},
"esniff": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
"requires": {
"d": "^1.0.1",
"es5-ext": "^0.10.62",
"event-emitter": "^0.3.5",
"type": "^2.7.2"
}
},
"espree": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
@ -5290,6 +5505,15 @@
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
},
"event-emitter": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
"requires": {
"d": "1",
"es5-ext": "~0.10.14"
}
},
"event-pubsub": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
@ -5392,6 +5616,19 @@
"vary": "~1.1.2"
}
},
"ext": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
"requires": {
"type": "^2.7.2"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extend-shallow": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
@ -5470,6 +5707,11 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"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": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
@ -5775,6 +6017,11 @@
"integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
"dev": true
},
"functions-have-names": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
},
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@ -5919,7 +6166,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"requires": {
"es-define-property": "^1.0.0"
}
@ -6099,6 +6345,11 @@
"integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==",
"dev": true
},
"html-void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz",
"integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A=="
},
"html-webpack-plugin": {
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz",
@ -6207,6 +6458,14 @@
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true
},
"i18next": {
"version": "20.6.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz",
"integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==",
"requires": {
"@babel/runtime": "^7.12.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@ -6240,6 +6499,11 @@
"dev": true,
"optional": true
},
"immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
},
"immutable": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
@ -6301,6 +6565,15 @@
"hasown": "^2.0.0"
}
},
"is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"requires": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
}
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@ -6346,6 +6619,15 @@
"hasown": "^2.0.0"
}
},
"is-date-object": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"requires": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
}
},
"is-descriptor": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz",
@ -6394,6 +6676,11 @@
"is-extglob": "^2.1.1"
}
},
"is-hotkey": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz",
"integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw=="
},
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
@ -6437,6 +6724,17 @@
"isobject": "^3.0.1"
}
},
"is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"requires": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
}
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@ -6449,6 +6747,11 @@
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true
},
"is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
},
"is-what": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
@ -6748,11 +7051,25 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"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.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
},
"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": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
"dev": true
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.defaultsdeep": {
"version": "4.6.1",
@ -6760,6 +7077,16 @@
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
"dev": true
},
"lodash.foreach": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ=="
},
"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": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
@ -6784,6 +7111,16 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
},
"lodash.toarray": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
"integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw=="
},
"lodash.truncate": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
@ -7062,6 +7399,21 @@
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz",
"integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
"requires": {
"wildcard": "^1.1.0"
},
"dependencies": {
"wildcard": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz",
"integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
}
}
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
@ -7273,6 +7625,11 @@
"thenify-all": "^1.0.0"
}
},
"namespace-emitter": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
"integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g=="
},
"nanoid": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
@ -7336,6 +7693,11 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@ -7442,8 +7804,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"object-copy": {
"version": "0.1.0",
@ -7478,11 +7839,19 @@
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="
},
"object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"requires": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object-visit": {
"version": "1.0.1",
@ -7706,6 +8075,11 @@
"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": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -8242,6 +8616,11 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"preact": {
"version": "10.26.9",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.26.9.tgz",
"integrity": "sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA=="
},
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -8264,6 +8643,11 @@
"renderkid": "^3.0.0"
}
},
"prismjs": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -8440,6 +8824,34 @@
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"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": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -8564,6 +8976,19 @@
"safe-regex": "^1.1.0"
}
},
"regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"requires": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
"es-errors": "^1.3.0",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"set-function-name": "^2.0.2"
}
},
"regexpp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
@ -8911,6 +9336,14 @@
"ajv-keywords": "^3.5.2"
}
},
"scroll-into-view-if-needed": {
"version": "2.2.31",
"resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
"integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
"requires": {
"compute-scroll-into-view": "^1.0.20"
}
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@ -9042,7 +9475,6 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"requires": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@ -9052,6 +9484,17 @@
"has-property-descriptors": "^1.0.2"
}
},
"set-function-name": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"requires": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
"has-property-descriptors": "^1.0.2"
}
},
"set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@ -9235,6 +9678,38 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true
},
"slate": {
"version": "0.72.8",
"resolved": "https://registry.npmjs.org/slate/-/slate-0.72.8.tgz",
"integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
"requires": {
"immer": "^9.0.6",
"is-plain-object": "^5.0.0",
"tiny-warning": "^1.0.3"
},
"dependencies": {
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
}
}
},
"slate-history": {
"version": "0.66.0",
"resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.66.0.tgz",
"integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==",
"requires": {
"is-plain-object": "^5.0.0"
},
"dependencies": {
"is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
}
}
},
"slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
@ -9257,6 +9732,11 @@
}
}
},
"snabbdom": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.2.tgz",
"integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q=="
},
"snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -9517,6 +9997,11 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"ssr-window": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-3.0.0.tgz",
"integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA=="
},
"ssri": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
@ -9909,6 +10394,11 @@
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
"dev": true
},
"tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"to-object-path": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
@ -9969,6 +10459,11 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
},
"type": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@ -10359,6 +10854,60 @@
}
}
},
"vue-quill-editor": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz",
"integrity": "sha512-g20oSZNWg8Hbu41Kinjd55e235qVWPLfg4NvsLW6d+DhgBTFbEuMpcWlUdrD6qT3+Noim6DRu18VLM9lVShXOQ==",
"requires": {
"object-assign": "^4.1.1",
"quill": "^1.3.4"
},
"dependencies": {
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="
},
"eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
},
"fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
},
"parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
},
"quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"requires": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
}
},
"quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"requires": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
}
}
}
},
"vue-router": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.6.5.tgz",

View File

@ -11,15 +11,20 @@
"dependencies": {
"@dreysolano/prerender-spa-plugin": "^1.0.3",
"@stomp/stompjs": "^7.1.1",
"@tinymce/tinymce-vue": "^6.2.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^1.0.2",
"amfe-flexible": "^2.2.1",
"axios": "^1.8.4",
"core-js": "^3.8.3",
"echarts": "^5.5.1",
"element-ui": "^2.15.14",
"jsencrypt": "^3.3.2",
"quill": "^2.0.3",
"vue": "^2.6.14",
"vue-i18n": "^8.22.2",
"vue-meta-info": "^0.1.7",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},

View File

@ -0,0 +1,59 @@
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
})
}

View File

@ -381,6 +381,8 @@ export default {
console.log("token变化打印",val);
if (!val) {
//
localStorage.setItem('cs_disconnect_all', Date.now().toString());
this.forceDisconnectAll()
this.$nextTick(() => {
this.determineUserType()
@ -1252,6 +1254,7 @@ export default {
return;
}
// === 线 ===
console.log("客服状态",this.customerIsOnline,`用户身份`,this.userType,`用户邮箱`,this.userEmail);
if (this.userType === 0 && this.customerIsOnline === false) {
this.$message({
message:
@ -2020,6 +2023,8 @@ export default {
// isWebSocketConnected: this.isWebSocketConnected,
// });
this.fetchUserid({ email: this.userEmail })
console.log("请求客服状态",this.userEmail);
const wasOpen = this.isChatOpen;
this.isChatOpen = !this.isChatOpen;

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +1,137 @@
<template>
<el-aside
style="height: 100vh; background: #202940;width: 280px;padding: 0;"
<el-aside
style="height: 100vh; background: #202940; width: 280px; padding: 0"
class="admin-sidebar"
>
<el-menu
style="border: none;width: 280px;"
style="border: none; width: 280px"
:default-active="activeIndex"
class="el-menu-vertical-demo"
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;">
<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>
<span slot="title">{{ $t(item.label) }}</span>
</el-menu-item>
<el-submenu :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-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(){
data() {
return {
menuList:[
{//广
path:"broadcast",
label:`backendSystem.broadcast`,
icon:"el-icon-bell",
id:"1",
menuList: [
// {
// //广
// path: "broadcast",
// label: `backendSystem.broadcast`,
// icon: "el-icon-bell",
// id: "1",
// },
{
//
path: "userManagement",
label: `backendSystem.userManagement`,
icon: "el-icon-user",
id: "2",
},
{//
path:"userManagement",
label:`backendSystem.userManagement`,
icon:"el-icon-user",
id:"2",
{
//
path: "workOrderBackend",
label: `backendSystem.workOrder`,
icon: "el-icon-document-copy",
id: "3",
},
{//
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(){
mounted() {
const lang = this.$i18n.locale;
const currentPath = this.$route.path.replace(`/${lang}/`, '');
const currentPath = this.$route.path.replace(`/${lang}/`, "");
//
const matchedMenu = this.menuList.find(item => item.path === currentPath);
const matchedMenu = this.menuList.find((item) => item.path === currentPath);
if (matchedMenu) {
this.activeIndex = matchedMenu.id;
this.$addStorageEvent(1, "activeIndex", matchedMenu.id);
} else {
// localStoragelocalStorage
const savedIndex = localStorage.getItem("activeIndex");
if(savedIndex){
if (savedIndex) {
this.activeIndex = savedIndex;
} else {
this.$addStorageEvent(1, "activeIndex", this.activeIndex);
}
}
},
methods:{
handleClick(item){
console.log(item,'item');
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);
}
this.$addStorageEvent(1, "activeIndex", item.id);
},
},
beforeDestroy(){
beforeDestroy() {
localStorage.removeItem("activeIndex");
}
},
};
</script>
<style scoped lang="scss">
.el-submenu .el-menu-item{
.el-submenu .el-menu-item {
padding-left: 40px !important;
}
</style>

View File

@ -248,6 +248,7 @@
<li class="register" @click="handelRegister">
{{ $t(`user.register`) }}
</li>
<!-- 帮助中心 -->
<li
class="personalCenter"
style="margin-left: 20px;"
@ -974,7 +975,7 @@ export default {
}
</style>
<style lang="scss" >
<style lang="scss" scoped>
.el-submenu__title:hover {
background-color: transparent !important;
background: transparent !important;

View File

@ -95,7 +95,12 @@ export const backendSystem_zh = {
invalidPath:"无效的跳转地址",
invalidPathSuggestions:"建议使用",
pathNumberNotMatch:"按钮数量和路径数量不匹配",
documentManagement:"文档管理",
addDocument:"新增文档",
allocationAmount:"分配金额",
transferAmount:"转账金额",
updateSuccess:"修改成功",
publishArticle:"发布文章",
}
}
@ -197,7 +202,13 @@ export const backendSystem_en = {
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",
}
}

View File

@ -33,6 +33,10 @@ export const seo_zh = {
userManagement: "M2Pool 矿池用户管理页面,管理员可在此查看所有用户信息,包括用户名、邮箱、注册时间、登录时间等。",
helpCenter:"M2Pool 矿池帮助中心页面,提供用户全面的帮助中心信息,包括新手入门、矿业数据、常见问题、公告中心、其他等。",
announcements:"M2Pool 矿池公告中心页面,提供最新的矿池公告、系统通知、服务更新和重要信息,让用户及时了解矿池动态和政策变更。",
documentManagement:"M2Pool 矿池文档管理页面,提供最新的文档信息,让用户及时了解文档信息。",
}
}
export const seo_en = {
@ -60,7 +64,7 @@ export const seo_en = {
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.",
}
}

View File

@ -15,6 +15,8 @@ import networkRecoveryMixin from './mixins/networkRecoveryMixin';
import './utils/loadingRecovery';
import errorNotificationManager from '../src/utils/errorNotificationManager';
// 创建事件总线 用于组件通信
Vue.prototype.$bus = new Vue();

View File

@ -90,6 +90,38 @@ const childrenRoutes = [
}
}
},
{//编辑器测试
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: '帮助中心,新手入门,常见问题,公告中心'
}
}
},
{//编辑器测试markdown
path: 'markdown',
name: 'Markdown',
component: () => import('../views/markdown.vue'),
meta: {
title: 'markdown编辑器测试',
// description: i18n.t(`seo.helpCenter`),
allAuthority: [`all`],
// keywords: {
// en: 'Help Center,Beginner Guide,Mining Data,Frequently Asked Questions,Announcement Center,Other',
// zh: '帮助中心,新手入门,常见问题,公告中心'
// }
}
},
{//广播页面
@ -135,7 +167,48 @@ const childrenRoutes = [
}
}
},
{//文档管理
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: '文档管理'
}
}
},
{//费率
@ -659,6 +732,20 @@ 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: '分屏编辑器,富文本编辑器,实时预览,所见即所得编辑器'
}
}
},

View File

@ -0,0 +1,86 @@
import { documentsList,findDataInfo } from '../../api/documentManagement'
export default{
data(){
return{
params:{
lang:"",
type: 1 // 服务条款类型数字1
},
infoParams:{
id:"",
lang:"",
},
// 存储从后端获取的文档内容
info: "",
// 加载状态
loading: false
}
},
mounted(){
this.params.lang = this.$i18n?.locale || 'zh'
this.fetchDocumentsList(this.params)
},
methods:{
/**
* 获取文档列表
*/
async fetchDocumentsList(){
try {
this.loading = true
const res = await documentsList(this.params)
console.log('文档列表:', res)
if (res && res.code === 200 && res.data && res.data.length > 0) {
console.log('请求参数:', res.data)
this.infoParams.id = res.data[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(){
try {
if (!this.infoParams.id) {
console.warn('文档ID为空无法获取文档内容')
return
}
const res = await findDataInfo(this.infoParams)
console.log('文档内容:', res)
if (res && res.code === 200 && res.data) {
// wangeditor 直接输出 HTML直接使用
this.info = res.data.content || ""
} else {
console.warn('获取文档内容失败:', res)
this.info = ""
}
} catch (error) {
console.error('获取文档内容失败:', error)
this.info = ""
}
},
}
}

View File

@ -1,5 +1,28 @@
<template>
<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">正在加载文档内容...</span>
</div>
<div v-else-if="info && info.trim()" class="dynamic-content" v-html="info"></div>
<!-- 如果没有动态内容显示提示信息 -->
<div v-else class="no-content">
<p>暂无自定义文档内容</p>
</div>
</section>
<!--
<section v-if="$isMobile">
<h4 >{{ $t(`ServiceTerms.title`) }}</h4>
@ -89,13 +112,7 @@
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
</div>
</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>
@ -189,21 +206,17 @@
<p>{{ $t(`ServiceTerms.clauseTermination2`) }}</p>
</div>
</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>
</template>
<script>
import Index from './index'
export default {
mixins: [Index],
metaInfo: {
meta: [
{
@ -250,6 +263,87 @@ export default {
}
}
//
.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;
// 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;
}
}
}
}
}
@ -283,4 +377,95 @@ 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;
// 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;
}
}
}
}
</style>

View File

@ -29,6 +29,298 @@
</el-button-group>
</div>
</div>
<!-- Markdown 使用规则指南 -->
<div class="markdown-guide-section" v-if="showMarkdownGuide">
<!-- 可展开的使用规则内容 -->
<transition name="slide-fade">
<div v-show="showMarkdownGuide" class="markdown-guide-content">
<div class="guide-container">
<h3 class="guide-title">📝 Markdown 语法规则详解</h3>
<!-- 标题语法 -->
<div class="guide-section">
<h4>1. 标题语法 (#符号)</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code># 一级标题 (最大)
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题 (最小)</code></pre>
</div>
<div class="result-preview">
<h1 style="font-size: 24px; margin: 8px 0;">一级标题</h1>
<h2 style="font-size: 20px; margin: 6px 0;">二级标题</h2>
<h3 style="font-size: 16px; margin: 4px 0;">三级标题</h3>
</div>
</div>
</div>
<!-- 文本格式化 -->
<div class="guide-section">
<h4>2. 文本格式化</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>**粗体文本**
*斜体文本*
***粗斜体***
~~删除线~~
`行内代码`</code></pre>
</div>
<div class="result-preview">
<p><strong>粗体文本</strong></p>
<p><em>斜体文本</em></p>
<p><strong><em>粗斜体</em></strong></p>
<p><del>删除线</del></p>
<p><code>行内代码</code></p>
</div>
</div>
</div>
<!-- 列表语法 -->
<div class="guide-section">
<h4>3. 列表语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>- 无序列表项 1
- 无序列表项 2
- 子列表项 2.1
- 子列表项 2.2
1. 有序列表项 1
2. 有序列表项 2
3. 有序列表项 3</code></pre>
</div>
<div class="result-preview">
<ul>
<li>无序列表项 1</li>
<li>无序列表项 2
<ul>
<li>子列表项 2.1</li>
<li>子列表项 2.2</li>
</ul>
</li>
</ul>
<ol>
<li>有序列表项 1</li>
<li>有序列表项 2</li>
<li>有序列表项 3</li>
</ol>
</div>
</div>
</div>
<!-- 链接和图片 -->
<div class="guide-section">
<h4>4. 链接和图片</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>[链接文本](https://example.com)
![图片描述](https://example.com/image.png)
参考式链接
[链接文本][1]
[1]: https://example.com</code></pre>
</div>
<div class="result-preview">
<p><a href="#" style="color: #5721E4;">链接文本</a></p>
<p>📷 图片会在这里显示</p>
<p><a href="#" style="color: #5721E4;">参考式链接</a></p>
</div>
</div>
</div>
<!-- 代码块 -->
<div class="guide-section">
<h4>5. 代码块</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>```javascript
function hello() {
console.log("Hello World!");
}
```
```python
def hello():
print("Hello World!")
```</code></pre>
</div>
<div class="result-preview">
<pre style="background: #f8f9fa; padding: 12px; border-radius: 4px;"><code>function hello() {
console.log("Hello World!");
}</code></pre>
</div>
</div>
</div>
<!-- 表格 -->
<div class="guide-section">
<h4>6. 表格语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>| 列标题1 | 列标题2 | 列标题3 |
|---------|---------|---------|
| 单元格1 | 单元格2 | 单元格3 |
| 数据A | 数据B | 数据C |
对齐方式
| 左对齐 | 居中对齐 | 右对齐 |
|:-------|:--------:|-------:|
| | | |</code></pre>
</div>
<div class="result-preview">
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr style="background: #f8f9fa;">
<th style="border: 1px solid #ddd; padding: 8px;">列标题1</th>
<th style="border: 1px solid #ddd; padding: 8px;">列标题2</th>
<th style="border: 1px solid #ddd; padding: 8px;">列标题3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">单元格1</td>
<td style="border: 1px solid #ddd; padding: 8px;">单元格2</td>
<td style="border: 1px solid #ddd; padding: 8px;">单元格3</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- 引用 -->
<div class="guide-section">
<h4>7. 引用语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>> 这是一个引用块
> 可以包含多行内容
>
> > 嵌套引用
> > 可以多层嵌套</code></pre>
</div>
<div class="result-preview">
<blockquote style="border-left: 4px solid #5721E4; padding-left: 16px; margin: 16px 0; color: #666;">
<p>这是一个引用块<br>可以包含多行内容</p>
<blockquote style="border-left: 4px solid #ccc; padding-left: 16px;">
<p>嵌套引用<br>可以多层嵌套</p>
</blockquote>
</blockquote>
</div>
</div>
</div>
<!-- 分隔线 -->
<div class="guide-section">
<h4>8. 分隔线</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>--- (三个或更多短横线)
*** (三个或更多星号)
___ (三个或更多下划线)</code></pre>
</div>
<div class="result-preview">
<hr style="border: none; border-top: 1px solid #ddd; margin: 16px 0;">
</div>
</div>
</div>
<!-- 任务列表 -->
<div class="guide-section">
<h4>9. 任务列表</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>- [x] 已完成任务
- [ ] 待完成任务
- [x] 另一个已完成任务</code></pre>
</div>
<div class="result-preview">
<ul style="list-style: none; padding-left: 0;">
<li> 已完成任务</li>
<li> 待完成任务</li>
<li> 另一个已完成任务</li>
</ul>
</div>
</div>
</div>
<!-- 转义字符 -->
<div class="guide-section">
<h4>10. 转义字符</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>\* 显示星号而不是斜体
\# 显示井号而不是标题
\` 显示反引号
\\ 显示反斜杠</code></pre>
</div>
<div class="result-preview">
<p>* 显示星号而不是斜体</p>
<p># 显示井号而不是标题</p>
<p>` 显示反引号</p>
<p>\ 显示反斜杠</p>
</div>
</div>
</div>
<!-- 快捷提示 -->
<div class="guide-section tips-section">
<h4>💡 实用提示</h4>
<div class="tips-grid">
<div class="tip-item">
<strong>标题层级</strong>按逻辑顺序使用不跳级
</div>
<div class="tip-item">
<strong>空行</strong>在不同元素之间添加空行提高可读性
</div>
<div class="tip-item">
<strong>列表缩进</strong>子列表用2个空格缩进
</div>
<div class="tip-item">
<strong>代码语言</strong>指定代码块语言以获得语法高亮
</div>
<div class="tip-item">
<strong>表格对齐</strong>保持表格列的对齐美观
</div>
<div class="tip-item">
<strong>链接描述</strong>使用有意义的链接文本
</div>
</div>
</div>
<!-- 常用快捷键 -->
<div class="guide-section">
<h4> 编辑器快捷键</h4>
<div class="shortcuts-grid">
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>B</kbd> 粗体
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>I</kbd> 斜体
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>K</kbd> 插入链接
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>`</kbd> → 行内代码
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>1-6</kbd> 标题
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>Z</kbd> 撤销
</div>
</div>
</div>
</div>
</div>
</transition>
</div>
<!-- 最新公告标题 -->
<div class="latest-section">
@ -77,6 +369,16 @@
>
{{ $t('home.viewAll') || '查看所有' }} {{ totalCount }} {{ $t('home.articles') || '篇文章' }}
</el-button>
<!-- 了解使用规则按钮 -->
<el-button
type="text"
class="markdown-guide-btn"
@click="toggleMarkdownGuide"
:icon="showMarkdownGuide ? 'el-icon-arrow-up' : 'el-icon-question'"
>
{{ showMarkdownGuide ? '隐藏' : '了解' }}Markdown使用规则
</el-button>
</div>
<!-- 分页组件 -->
@ -167,7 +469,11 @@ export default {
],
//
searchTimer: null
searchTimer: null,
// Markdown 使
showMarkdownGuide: false,
viewMode: 'list' // 'list' or 'editor'
}
},
@ -252,6 +558,21 @@ export default {
this.loadAnnouncements();
},
/**
* 切换Markdown使用规则指南的显示状态
*/
toggleMarkdownGuide() {
this.showMarkdownGuide = !this.showMarkdownGuide;
},
/**
* 切换视图模式 (list/editor)
*/
switchMode(mode) {
this.viewMode = mode;
// Markdown
},
/**
* 返回首页
*/
@ -358,6 +679,180 @@ export default {
margin: 0;
}
/* Markdown 使用规则指南 */
.markdown-guide-section {
padding: 30px 40px 20px;
border-bottom: 1px solid #f0f0f0;
}
.guide-header {
display: flex;
justify-content: flex-start;
margin-bottom: 20px;
}
.guide-toggle-btn {
font-size: 14px;
color: #5721E4;
text-decoration: none;
transition: color 0.3s ease;
&:hover {
color: #5721E4;
text-decoration: underline;
}
}
.markdown-guide-content {
background: #f8f9ff;
border-radius: 8px;
padding: 20px;
border: 1px solid #e0e0e0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
}
.guide-container {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-in-out;
}
.guide-container.show {
max-height: 1000px; /* 足够大的高度,确保所有内容都可见 */
}
.guide-title {
font-size: 20px;
font-weight: 600;
color: #34495e;
margin-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 10px;
}
.guide-section {
margin-bottom: 25px;
padding-bottom: 20px;
border-bottom: 1px dashed #eee;
&:last-child {
border-bottom: none;
padding-bottom: 0;
}
}
.guide-section h4 {
font-size: 16px;
font-weight: 500;
color: #4a4a4a;
margin-bottom: 15px;
position: relative;
padding-left: 15px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 15px;
background: #5721E4;
border-radius: 2px;
}
}
.example-container {
display: flex;
gap: 20px;
margin-bottom: 15px;
}
.syntax-example {
flex: 1;
background: #f0f0f0;
border-radius: 4px;
padding: 10px;
overflow-x: auto;
font-size: 14px;
color: #333;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-all;
border: 1px solid #ccc;
}
.result-preview {
flex: 1;
padding: 10px;
background: #fff;
border-radius: 4px;
border: 1px solid #eee;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
min-height: 100px; /* Ensure some height for preview */
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
font-size: 14px;
color: #555;
line-height: 1.8;
}
.tips-section {
margin-top: 20px;
padding-top: 20px;
border-top: 1px dashed #eee;
}
.tips-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-top: 15px;
}
.tip-item {
background: #f0edff;
padding: 10px 15px;
border-radius: 6px;
font-size: 13px;
color: #5721E4;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
.shortcuts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin-top: 15px;
}
.shortcut-item {
background: #f0edff;
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
color: #5721E4;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
.shortcut-item kbd {
background-color: #e0e0e0;
border-radius: 4px;
padding: 2px 4px;
font-size: 12px;
font-family: monospace;
color: #333;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
}
/* 最新公告标题 */
.latest-section {
padding: 30px 40px 20px;
@ -494,6 +989,11 @@ export default {
.view-all-button {
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.view-all-link {
@ -506,6 +1006,24 @@ export default {
}
}
/* Markdown指南按钮样式 */
.markdown-guide-btn {
font-size: 14px;
color: #5721E4 !important;
font-weight: 500;
transition: all 0.3s ease;
border: 1px solid #5721E4;
border-radius: 4px;
padding: 8px 16px;
&:hover {
color: #fff !important;
background-color: #5721E4 !important;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(87, 33, 228, 0.3);
}
}
.pagination {
justify-content: center;
@ -556,6 +1074,55 @@ export default {
.main-content {
border-radius: 8px;
}
.markdown-guide-section {
padding: 15px 20px;
}
.guide-header {
justify-content: center;
}
.guide-toggle-btn {
font-size: 13px;
}
.markdown-guide-content {
padding: 10px;
}
.guide-container {
max-height: none; /* Allow content to wrap */
}
.guide-container.show {
max-height: none;
}
.example-container {
flex-direction: column;
gap: 10px;
}
.syntax-example,
.result-preview {
width: 100%;
}
.tips-grid,
.shortcuts-grid {
grid-template-columns: 1fr;
}
.tip-item,
.shortcut-item {
justify-content: flex-start;
padding-left: 15px;
}
.shortcut-item kbd {
font-size: 11px;
}
.page-header,
.latest-section,
@ -590,6 +1157,17 @@ export default {
align-items: flex-start;
gap: 4px;
}
/* 移动端按钮样式调整 */
.view-all-button {
flex-direction: column;
gap: 12px;
}
.markdown-guide-btn {
font-size: 13px;
padding: 6px 12px;
}
}
/* 深色模式适配 */
@ -603,6 +1181,48 @@ export default {
background: #2d2d2d;
color: #fff;
}
.markdown-guide-section {
background: #2d2d2d;
border-color: #3a3a3a;
}
.guide-title,
.guide-section h4 {
color: #fff;
}
.syntax-example {
background: #3a3a3a;
border-color: #555;
color: #ccc;
}
.result-preview {
background: #333;
border-color: #555;
color: #bbb;
}
.tips-section {
border-top-color: #3a3a3a;
}
.tip-item {
background: #3a3a3a;
color: #888;
}
.shortcut-item {
background: #3a3a3a;
color: #888;
}
.shortcut-item kbd {
background-color: #444;
color: #eee;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
}
.page-title,
.section-title,
@ -622,4 +1242,19 @@ export default {
color: #999;
}
}
/* 展开/收起动画 */
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.3s ease;
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateY(-10px);
opacity: 0;
}
</style>

View File

@ -1,4 +1,4 @@
import { documentsList, findDataInfo } from '../../api/staticDocumentManagement'
import { documentsList, findDataInfo } from '../../api/documentManagement'
export default {
name: 'ApiFile',

View File

@ -1,8 +1,8 @@
<template>
<div class="rate">
<section class="navContent">
<!-- 动态文档内容渲染区域 -->
<!-- 动态文档内容渲染区域 -->
<!-- <section class="navContent">
<div v-if="documentLoading" class="loading-container">
<p>正在加载文档...</p>
</div>
@ -11,7 +11,7 @@
<p>{{ documentError }}</p>
</div>
</section>
-->
@ -2384,4 +2384,103 @@ a{
}
}
/* 主容器样式 */
.navContent {
background: #ffffff; /* 白色背景 */
padding: 24px; /* 统一内边距 */
border-radius: 12px; /* 圆角 */
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05); /* 轻微阴影 */
margin-bottom: 20px;
}
/* 加载状态样式 */
.loading-container {
background: #f8f9fa; /* 浅灰背景 */
padding: 40px 20px; /* 上下40px左右20px */
text-align: center;
border-radius: 8px;
border: 1px solid #e9ecef;
}
.loading-container p {
color: #6c757d;
font-size: 14px;
margin: 0;
/* 可以添加加载动画 */
animation: pulse 1.5s ease-in-out infinite;
}
/* 文档内容样式 */
.document-content {
background: #ffffff; /* 纯白背景 */
padding: 20px; /* 内容区域内边距 */
border-radius: 8px;
line-height: 1.6;
color: #2c3e50;
/* 如果内容过长,添加滚动 */
max-height: 70vh;
overflow-y: auto;
}
/* 错误状态样式 */
.error-container {
background: #fef5f5; /* 淡红背景 */
padding: 30px 20px;
text-align: center;
border-radius: 8px;
border: 1px solid #fecaca;
}
.error-container p {
color: #dc2626; /* 红色文字 */
font-size: 14px;
margin: 0;
}
/* 加载动画 */
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
/* 响应式设计 */
@media (max-width: 768px) {
.navContent {
padding: 16px; /* 移动端减少内边距 */
margin: 10px;
}
.document-content {
padding: 15px;
max-height: 60vh; /* 移动端调整最大高度 */
}
.loading-container,
.error-container {
padding: 25px 15px;
}
}
</style>

View File

@ -9,7 +9,7 @@
</div>
<!-- 添加连接状态提示 -->
<div
v-if="connectionStatus !== 'connected'"
v-if="connectionStatus !== 'connected' && connectionStatus !== 'error'"
class="connection-status"
:class="connectionStatus"
>

View File

@ -0,0 +1,28 @@
import { findDataInfo } from "../../../api/documentManagement"
export default{
data(){
return{
}
},
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.content = this.modifyData.content
}
}
}
}

View File

@ -0,0 +1,772 @@
<template>
<div class="editor-page" v-loading="addLoading">
<!-- 页面头部 -->
<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 { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { addDocument } from '../../../api/documentManagement'
import Index from './index'
export default Vue.extend({
components: { Editor, Toolbar },
mixins: [Index],
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:"其他"
}
],
addLoading:false,
}
},
methods: {
async fetchAddDocument(params){
this.setLoading('addLoading', true);
const res = await addDocument(params)
if (res && res.code == 200) {
this.$message.success(this.$t('backendSystem.addSuccess'));
this.$router.push({ path: `/${this.$i18n.locale}/documentManagement` })
}
this.setLoading('addLoading', false);
},
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 {
width: 100%;
margin: 0 auto;
padding: 20px;
background: #f8f9fa;
min-height: 60vh;
overflow-y: auto;
}
/* 页面头部样式 */
.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>
<style src="@wangeditor/editor/dist/css/style.css"></style>

View File

@ -0,0 +1,446 @@
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:"挖矿教程"
},
{
value:"2",
label:"常见问题"
},
{
value:"3",
label:"公告中心"
},
{
value:"0",
label:"其他"
}
],
queryParams:{
keyword:"",
type:"",
},
}
},
mounted() {
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) {
console.log(`每页 ${val}`);
this.listParams.pageSize = val
this.listParams.pageNum = 1
this.currentPage = 1
this.fetchListData(this.listParams);
},
handleCurrentChange(val) {
console.log(`当前页: ${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 {
return this.TypeList.find(item => item.value == type).label
} catch (error) {
return ''
}
},
changeScreen(type){
this.listParams.type = type
this.fetchListData(this.listParams);
},
handelQuery(){
},
handleInputClear(){
// this.queryParams.keyword = ''
// this.queryParams.type = ''
// this.fetchListData(this.listParams);
}
},
}

View File

@ -0,0 +1,165 @@
<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="文档类型" prop="type">
<el-select
class="input"
size="middle"
ref="screen"
@change="changeScreen(queryParams.type)"
v-model="queryParams.type"
:placeholder="$t(`personal.screen`)"
>
<el-option
v-for="item in TypeList"
:key="item.value"
:label="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">
{{ item.label }}</span
>
</div>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="搜索" 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="创建时间" width="160" show-overflow-tooltip >
<template slot-scope="scope">
{{handelTime(scope.row.createTime)}}
</template>
</el-table-column>
<el-table-column prop="createUser" label="创建人" width="160" show-overflow-tooltip />
<el-table-column prop="content" label="文档内容" show-overflow-tooltip />
<el-table-column prop="title" label="文档标题" width="200" show-overflow-tooltip />
<el-table-column prop="type" label="文档类型" width="100" show-overflow-tooltip >
<template slot-scope="scope">
{{handelType(scope.row.type)}}
</template>
</el-table-column>
<el-table-column prop="updateTime" label="修改时间" width="160" show-overflow-tooltip >
<template slot-scope="scope">
{{handelTime(scope.row.updateTime)}}
</template>
</el-table-column>
<el-table-column prop="updateUser" label="修改人" 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="userListParams.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>

View File

@ -0,0 +1,28 @@
import { findDataInfo } from "../../../api/documentManagement"
export default{
data(){
return{
}
},
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.content = this.modifyData.content
}
}
}
}

View File

@ -0,0 +1,774 @@
<template>
<div class="editor-page" v-loading="addLoading">
<!-- 页面头部 -->
<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 { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { updateDocument } from '../../../api/documentManagement'
import Index from './index'
export default Vue.extend({
components: { Editor, Toolbar },
mixins: [Index],
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:"其他"
}
],
addLoading:false,
}
},
methods: {
async fetchUpdateDocument(params){
this.setLoading('addLoading', true);
const res = await updateDocument(params)
if (res && res.code == 200) {
this.$message.success(this.$t('backendSystem.updateSuccess'));
this.$router.push({ path: `/${this.$i18n.locale}/documentManagement` })
}
this.setLoading('addLoading', false);
},
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.addParams.lang = this.$i18n.locale
this.addParams.id = this.$route.query.id
this.fetchUpdateDocument(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,
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.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 {
width: 100%;
margin: 0 auto;
padding: 20px;
background: #f8f9fa;
min-height: 60vh;
overflow-y: auto;
}
/* 页面头部样式 */
.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>
<style src="@wangeditor/editor/dist/css/style.css"></style>

View File

@ -0,0 +1,762 @@
<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 { Editor, Toolbar } from '@wangeditor/editor-for-vue'
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>
<style src="@wangeditor/editor/dist/css/style.css"></style>

View File

@ -1272,7 +1272,10 @@ export default {
this.minerOption.xAxis.data = xData
this.minerOption.yAxis[0].name = MinerCount[0].unit
if (MinerCount[0] && MinerCount[0].unit) {
this.minerOption.yAxis[0].name = MinerCount[0].unit
}
this.minerOption.series[0].data = pvData
this.minerOption.series[1].data = price
this.$nextTick(() => {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,671 @@
<template>
<div class="split-editor-demo">
<!-- 页面头部 -->
<div class="page-header">
<div class="header-content">
<h1 class="page-title">
<i class="el-icon-s-unfold"></i>
分屏编辑器演示
</h1>
<p class="page-subtitle">支持编辑预览分屏三种模式的富文本编辑器</p>
</div>
<div class="header-actions">
<el-button @click="handleSave" :loading="saveLoading" icon="el-icon-document" type="success">
保存内容
</el-button>
<el-button @click="handleClear" icon="el-icon-delete" type="danger">
清空内容
</el-button>
</div>
</div>
<!-- 文档配置区域 -->
<el-card class="document-config" shadow="never">
<div slot="header">
<span><i class="el-icon-setting"></i> 文档配置</span>
</div>
<el-form :model="documentForm" label-width="100px" class="config-form">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="文档标题">
<el-input v-model="documentForm.title" placeholder="请输入文档标题" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="文档类型">
<el-select v-model="documentForm.type" placeholder="请选择文档类型" style="width: 100%">
<el-option label="服务条款" value="1" />
<el-option label="API文档" value="2" />
<el-option label="挖矿教程" value="3" />
<el-option label="其他" value="0" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="文档状态">
<el-tag :type="documentForm.status === 'published' ? 'success' : 'info'">
{{ documentForm.status === 'published' ? '已发布' : '草稿' }}
</el-tag>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 分屏编辑器 -->
<el-card class="editor-card" shadow="never">
<div slot="header">
<span><i class="el-icon-edit-outline"></i> 分屏编辑器</span>
<div class="header-tips">
<el-tag size="mini" type="info">支持实时预览</el-tag>
<el-tag size="mini" type="success">自动保存</el-tag>
</div>
</div>
<SplitScreenEditor
ref="splitEditor"
v-model="documentForm.content"
:height="500"
:options="editorOptions"
@change="handleContentChange"
@publish="handlePublish"
/>
</el-card>
<!-- 使用说明 -->
<el-card class="usage-guide" shadow="never">
<div slot="header">
<span><i class="el-icon-info"></i> 使用说明</span>
<el-button
style="float: right; padding: 3px 0"
type="text"
@click="showGuide = !showGuide"
>
{{ showGuide ? '收起' : '展开' }}
</el-button>
</div>
<transition name="slide-fade">
<div v-show="showGuide" class="guide-content">
<div class="guide-section">
<h4>🖥 三种显示模式</h4>
<ul>
<li><strong>编辑模式</strong>只显示编辑器专注于内容编写</li>
<li><strong>预览模式</strong>只显示预览效果方便查看最终结果</li>
<li><strong>分屏模式</strong>左边编辑右边实时预览所见即所得</li>
</ul>
</div>
<div class="guide-section">
<h4> 快捷功能</h4>
<ul>
<li><strong>插入圆点</strong>点击工具栏中的"插入圆点"按钮在当前位置插入 符号</li>
<li><strong>全屏编辑</strong>点击全屏按钮或按 F11 进入全屏模式</li>
<li><strong>复制HTML</strong>在预览区域可以复制生成的HTML代码</li>
<li><strong>字数统计</strong>实时显示当前内容的字符数量</li>
</ul>
</div>
<div class="guide-section">
<h4>🎯 圆点列表示例</h4>
<p>在编辑器中输入以下内容来创建带圆点的列表</p>
<div class="example-box">
<p><code> ALEO矿工必须质押一定数量的ALEO代币</code></p>
<p><code> 否则将无法提交PoW工作量证明</code></p>
<p><code> 质押金额直接影响挖矿收益</code></p>
</div>
</div>
</div>
</transition>
</el-card>
</div>
</template>
<script>
import SplitScreenEditor from '@/components/SplitScreenEditor.vue'
export default {
name: 'SplitEditorDemo',
components: {
SplitScreenEditor
},
data() {
return {
//
documentForm: {
title: '分屏编辑器演示文档',
type: '2',
content: this.getDefaultContent(),
status: 'draft'
},
//
saveLoading: false,
// 使
showGuide: true,
//
editorOptions: {
height: 500,
menubar: false,
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
'preview', 'anchor', 'searchreplace', 'visualblocks', 'code',
'fullscreen', 'insertdatetime', 'media', 'table', 'help', 'wordcount'
],
toolbar: [
'undo redo | formatselect | bold italic underline strikethrough',
'forecolor backcolor | alignleft aligncenter alignright alignjustify',
'bullist numlist outdent indent | link image table',
'code preview fullscreen | removeformat help'
].join(' | '),
content_style: `
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #2c3e50;
margin: 16px;
}
p { margin: 10px 0; }
ul, ol { margin: 10px 0; padding-left: 24px; }
li { margin: 6px 0; line-height: 1.6; }
h1, h2, h3 { color: #2c3e50; margin: 16px 0 8px 0; }
table { border-collapse: collapse; width: 100%; margin: 12px 0; }
table th, table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
table th { background-color: #f2f2f2; font-weight: 600; }
code { background: #f4f4f4; padding: 2px 4px; border-radius: 3px; }
pre { background: #f8f8f8; padding: 12px; border-radius: 4px; overflow-x: auto; }
`,
placeholder: '请在此输入您的内容,支持富文本格式...',
language: 'zh_CN',
branding: false,
resize: false,
statusbar: true
}
}
},
methods: {
/**
* 获取默认内容 - 演示ALEO相关内容
*/
getDefaultContent() {
return `<h2>ALEO挖矿说明</h2>
<p>根据<a href="#" target="_blank">ALEO ARC-46协议</a>ALEO挖矿机制将在2025年08月01日00:00 UTC进行如下升级升级完成后您的ALEO挖矿可能会受到影响请您知悉</p>
<ol>
<li><strong>ALEO挖矿将转变为"PoS+PoW"混合机制</strong></li>
</ol>
<ul>
<li> ALEO矿工必须质押一定数量的ALEO代币否则将无法提交PoW工作量证明(即算力)并获得挖矿收益</li>
</ul>
<h3>重要提醒</h3>
<p>请及时了解新的挖矿机制要求做好相应准备如有疑问请联系客服获取帮助</p>
<h3>技术规格表</h3>
<table>
<thead>
<tr>
<th>参数</th>
<th>当前值</th>
<th>升级后</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>共识机制</td>
<td>PoW</td>
<td>PoS+PoW</td>
<td>混合共识</td>
</tr>
<tr>
<td>质押要求</td>
<td></td>
<td>必需</td>
<td>需要质押ALEO代币</td>
</tr>
<tr>
<td>算力证明</td>
<td>直接提交</td>
<td>需要质押</td>
<td>先质押后挖矿</td>
</tr>
</tbody>
</table>
<p><em>以上信息仅供参考具体实施以官方公告为准</em></p>`
},
/**
* 处理内容变化
*/
handleContentChange(content) {
console.log('编辑器内容已更改:', content.length, '字符');
//
this.autoSave();
},
/**
* 自动保存防抖
*/
autoSave() {
clearTimeout(this.autoSaveTimer);
this.autoSaveTimer = setTimeout(() => {
this.saveToDraft();
}, 2000); // 2
},
/**
* 保存到本地存储
*/
saveToDraft() {
const draftData = {
...this.documentForm,
lastSaved: new Date().toISOString()
};
localStorage.setItem('split_editor_draft', JSON.stringify(draftData));
console.log('内容已自动保存到本地');
},
/**
* 从本地存储加载草稿
*/
loadDraft() {
const draft = localStorage.getItem('split_editor_draft');
if (draft) {
try {
const draftData = JSON.parse(draft);
const timeDiff = new Date().getTime() - new Date(draftData.lastSaved).getTime();
// 稿24
if (timeDiff < 24 * 60 * 60 * 1000) {
this.documentForm = {
...this.documentForm,
...draftData
};
this.$message({
message: `已恢复草稿 (${new Date(draftData.lastSaved).toLocaleString()})`,
type: 'success',
duration: 3000
});
}
} catch (error) {
console.error('加载草稿失败:', error);
}
}
},
/**
* 保存内容
*/
async handleSave() {
if (!this.documentForm.title.trim()) {
this.$message.warning('请输入文档标题');
return;
}
if (!this.documentForm.content.trim()) {
this.$message.warning('请输入文档内容');
return;
}
this.saveLoading = true;
try {
// API
await new Promise(resolve => setTimeout(resolve, 1000));
// API
// const response = await addDocument(this.documentForm);
this.$message.success('文档保存成功');
this.documentForm.status = 'published';
// 稿
localStorage.removeItem('split_editor_draft');
} catch (error) {
console.error('保存失败:', error);
this.$message.error('保存失败: ' + (error.message || '未知错误'));
} finally {
this.saveLoading = false;
}
},
/**
* 清空内容
*/
handleClear() {
this.$confirm('确定要清空所有内容吗?此操作不可恢复。', '确认清空', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.documentForm.content = '';
this.documentForm.title = '';
this.$refs.splitEditor.clear();
// 稿
localStorage.removeItem('split_editor_draft');
this.$message.success('内容已清空');
}).catch(() => {
//
});
},
/**
* 处理编辑器发布事件
*/
handlePublish(publishData) {
console.log('编辑器发布数据:', publishData);
if (publishData.success) {
//
console.log('文档发布成功:', {
documentId: publishData.documentId,
title: publishData.title,
wordCount: publishData.wordCount
});
//
this.documentForm.title = publishData.title;
this.documentForm.content = publishData.content;
this.documentForm.status = 'published';
// 稿
this.clearDraft();
//
this.$notify({
title: '✅ 发布成功',
message: `文档 "${publishData.title}" 已成功发布到文档管理系统\n文档ID: ${publishData.documentId}\n字数: ${publishData.wordCount}`,
type: 'success',
duration: 5000
});
} else {
//
console.error('文档发布失败:', publishData.error);
this.$notify({
title: '❌ 发布失败',
message: `发布失败:${publishData.error}`,
type: 'error',
duration: 4000
});
}
}
},
mounted() {
// 稿
this.loadDraft();
},
beforeDestroy() {
//
if (this.autoSaveTimer) {
clearTimeout(this.autoSaveTimer);
}
}
}
</script>
<style scoped>
/* 页面容器 */
.split-editor-demo {
padding: 20px;
background: #f5f7fa;
min-height: calc(100vh - 140px);
}
/* 页面头部 */
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.header-content {
flex: 1;
}
.page-title {
margin: 0 0 8px 0;
color: #2c3e50;
font-size: 28px;
font-weight: 600;
display: flex;
align-items: center;
gap: 12px;
}
.page-title i {
color: #5721E4;
font-size: 32px;
}
.page-subtitle {
margin: 0;
color: #7f8c8d;
font-size: 14px;
line-height: 1.5;
}
.header-actions {
display: flex;
gap: 12px;
}
/* 文档配置 */
.document-config {
margin-bottom: 20px;
}
.document-config :deep(.el-card__header) {
background: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
font-weight: 600;
color: #2c3e50;
}
.document-config :deep(.el-card__header i) {
color: #5721E4;
margin-right: 8px;
}
.config-form .el-form-item {
margin-bottom: 16px;
}
/* 编辑器卡片 */
.editor-card {
margin-bottom: 20px;
}
.editor-card :deep(.el-card__header) {
background: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
font-weight: 600;
color: #2c3e50;
display: flex;
justify-content: space-between;
align-items: center;
}
.editor-card :deep(.el-card__header i) {
color: #5721E4;
margin-right: 8px;
}
.header-tips {
display: flex;
gap: 8px;
}
/* 使用指南 */
.usage-guide {
margin-bottom: 20px;
}
.usage-guide :deep(.el-card__header) {
background: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
font-weight: 600;
color: #2c3e50;
display: flex;
justify-content: space-between;
align-items: center;
}
.usage-guide :deep(.el-card__header i) {
color: #5721E4;
margin-right: 8px;
}
.guide-content {
padding: 10px 0;
}
.guide-section {
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 1px dashed #eee;
}
.guide-section:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.guide-section h4 {
font-size: 16px;
font-weight: 600;
color: #5721E4;
margin-bottom: 12px;
position: relative;
padding-left: 20px;
}
.guide-section h4::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: #5721E4;
border-radius: 2px;
}
.guide-section ul {
margin: 8px 0;
padding-left: 20px;
}
.guide-section li {
margin: 6px 0;
line-height: 1.6;
color: #2c3e50;
}
.guide-section li strong {
color: #5721E4;
font-weight: 600;
}
.example-box {
background: #f8f9fa;
border: 1px solid #e0e0e0;
border-radius: 6px;
padding: 12px;
margin: 8px 0;
}
.example-box p {
margin: 4px 0;
font-family: 'Monaco', 'Consolas', monospace;
font-size: 13px;
}
.example-box code {
background: #fff;
color: #e74c3c;
padding: 2px 6px;
border-radius: 3px;
border: 1px solid #ddd;
}
/* 展开/收起动画 */
.slide-fade-enter-active {
transition: all 0.4s ease;
}
.slide-fade-leave-active {
transition: all 0.4s ease;
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateY(-10px);
opacity: 0;
}
/* 响应式设计 */
@media screen and (max-width: 768px) {
.split-editor-demo {
padding: 10px;
}
.page-header {
flex-direction: column;
gap: 16px;
align-items: stretch;
}
.header-actions {
justify-content: center;
}
.config-form .el-row .el-col {
width: 100% !important;
margin-bottom: 12px;
}
.page-title {
font-size: 24px;
text-align: center;
}
.page-title i {
font-size: 28px;
}
.page-subtitle {
text-align: center;
}
.header-tips {
justify-content: center;
flex-wrap: wrap;
}
}
</style>

View File

@ -349,12 +349,95 @@ export default {
],
chartShow:true,
tableData:[],
tableData:[
// {
// "shouldOutDate":"2025-06-16T00:00:00",
// "allocationAmount":"27366620.96662387",
// "transferAmount":"27389920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-16T00:00:00",
// "allocationAmount":"",
// "transferAmount":"920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-16T00:00:00",
// "allocationAmount":"2720.96662387",
// "transferAmount":"920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-17T00:00:00",
// "allocationAmount":"273920.96662387",
// "transferAmount":"273920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-18T00:00:00",
// "allocationAmount":"273920.96662387",
// "transferAmount":"273920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-19T00:00:00",
// "allocationAmount":"273920.96662387",
// "transferAmount":"273920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-19T00:00:00",
// "allocationAmount":"2720.96662387",
// "transferAmount":"220.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-20T00:00:00",
// "allocationAmount":"273920.96662387",
// "transferAmount":"273920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
// {
// "shouldOutDate":"2025-06-21T00:00:00",
// "allocationAmount":"273920.96662387",
// "transferAmount":"273920.96662387",
// "address":"D7tviVPKtTd2qnkzJEVfZWQqzV6NyQqHxw",
// "maxHeight":"100000",
// },
],
historyBalance:[],
mergeConfig: {}, // 存储合并配置
}
},
watch: {
tableData: {
handler() {
this.calculateMergeConfig()
},
deep: true
}
},
mounted() {
let token
try{
@ -381,11 +464,23 @@ export default {
// 等待两个图表相关接口都完成后再调用inCharts
this.fetchChartData();
}
// this.calculateMergeConfig()
},
methods: {
/**
* 提取日期部分去掉时间
* @param {string} dateTimeString - 完整的日期时间字符串
* @returns {string} 日期部分
*/
extractDate(dateTimeString) {
if (!dateTimeString) return ''
return dateTimeString.split('T')[0]
},
//初始化图表
inCharts() {
if (this.myChart == null) {
@ -427,7 +522,10 @@ export default {
this.tableData = res.data.walletInInfo.sort((a, b) => new Date(b.createDate) - new Date(a.createDate));
this.noDataTip = false
}
// 🔥 在更新数据后重新计算合并配置
this.$nextTick(() => {
this.calculateMergeConfig()
})
}
this.setLoading('userDetailsLoading', false);
@ -534,8 +632,78 @@ export default {
// 等待两个图表相关接口都完成后再调用inCharts
this.fetchChartData();
},
handelTime(time){
return time.split("T")[0] + " " + time.split("T")[1]
/**
* 计算合并配置
* 根据 shouldOutDate 的日期部分进行分组和合并
*/
calculateMergeConfig() {
const dateGroups = {}
const mergeConfig = {}
// 按日期分组
this.tableData.forEach((row, index) => {
const dateKey = this.extractDate(row.shouldOutDate)
if (!dateGroups[dateKey]) {
dateGroups[dateKey] = []
}
dateGroups[dateKey].push(index)
})
// 计算每个日期组的合并信息
Object.values(dateGroups).forEach(group => {
if (group.length > 1) {
// 第一行显示合并的单元格
mergeConfig[group[0]] = {
shouldOutDate: group.length, // 合并的行数
}
// 其他行的日期列不显示
for (let i = 1; i < group.length; i++) {
mergeConfig[group[i]] = {
shouldOutDate: 0, // 0表示不显示
}
}
}
})
this.mergeConfig = mergeConfig
console.log('合并配置:', this.mergeConfig)
},
/**
* Element UI 表格合并单元格方法
* @param {Object} param0 - 包含行索引列索引等信息
* @returns {Array} [rowspan, colspan] 合并配置
*/
handleSpanMethod({ rowIndex, columnIndex }) {
// 列索引对应关系:
// 0: shouldOutDate (日期列)
// 1: allocationAmount
// 2: transferAmount
// 3: address
// 4: maxHeight
// 只对日期列索引为0进行合并
if (columnIndex === 0) {
const config = this.mergeConfig[rowIndex]
if (config && typeof config.shouldOutDate !== 'undefined') {
return [config.shouldOutDate, 1] // [rowspan, colspan]
}
}
return [1, 1] // 默认不合并
},
/**
* 处理时间显示如果你还需要这个方法
* @param {string} dateTime - 日期时间字符串
* @returns {string} 格式化后的日期
*/
handelTime(dateTime) {
if (!dateTime) return ''
return this.extractDate(dateTime)
}
}
}

View File

@ -136,27 +136,28 @@
<el-table
:data="tableData"
border
:span-method="handleSpanMethod"
:header-cell-style="{ 'text-align': 'center' }"
:cell-style="{ 'text-align': 'center' }"
height="42vh"
>
<el-table-column prop="createDate" :label="$t('backendSystem.createDate')" width="160" >
<!-- <el-table-column prop="createDate" :label="$t('backendSystem.createDate')" width="160" >
<template slot-scope="scope">
<span>{{ handelTime(scope.row.createDate ) }}</span>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column prop="shouldOutDate" :label="$t('backendSystem.shouldOutDate')" width="180" show-overflow-tooltip >
<template slot-scope="scope">
<span>{{ handelTime(scope.row.shouldOutDate ) }}</span>
</template>
</el-table-column>
<el-table-column prop="coin" :label="$t('backendSystem.coin2')" width="100" show-overflow-tooltip>
<!-- <el-table-column prop="coin" :label="$t('backendSystem.coin2')" width="100" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="amount" :label="$t('backendSystem.transactionAmount')" width="200" show-overflow-tooltip/>
</el-table-column> -->
<el-table-column prop="allocationAmount" :label="$t('backendSystem.allocationAmount')" width="200" show-overflow-tooltip/>
<el-table-column prop="transferAmount" :label="$t('backendSystem.transferAmount')" width="200" show-overflow-tooltip/>
<el-table-column prop="user" :label="$t('backendSystem.minerUser2')" width="180" show-overflow-tooltip/>
<!-- <el-table-column prop="user" :label="$t('backendSystem.minerUser2')" width="180" show-overflow-tooltip/> -->
<el-table-column prop="address" :label="$t('backendSystem.address')" show-overflow-tooltip />
<el-table-column prop="maxHeight" :label="$t('backendSystem.maxHeight')" width="180" show-overflow-tooltip />
@ -332,6 +333,8 @@ export default {
padding:1% 5%;
}
</style>
<style>
@ -340,4 +343,29 @@ export default {
color: #333 !important;
}
/* 合并单元格样式优化 */
::v-deep .el-table td {
vertical-align: middle;
}
/* 日期列样式 */
::v-deep .el-table .cell {
padding: 0 12px;
word-break: break-word;
}
/* 合并后的日期单元格突出显示 */
::v-deep .el-table tbody tr:hover > td {
background-color: #f5f7fa;
}
/* 表格边框优化 */
::v-deep .el-table--border td {
border-right: 1px solid #ebeef5;
}
::v-deep .el-table--border th {
border-right: 1px solid #ebeef5;
}
</style>

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=google-site-verification content=pKAZogQ0NQ6L4j9-V58WJMjm7zYCFwkJXSJzWu9UDM8><meta name=robots content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><meta name=googlebot content="index, follow"><meta name=googlebot-news content="index, follow"><meta name=bingbot content="index, follow"><link rel=alternate hreflang=zh href=https://m2pool.com/zh><link rel=alternate hreflang=en href=https://m2pool.com/en><link rel=alternate hreflang=x-default href=https://m2pool.com/en><meta property=og:title content="M2pool - Stable leading high-yield mining pool"><meta property=og:description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining"><meta property=og:url content=https://m2pool.com/en><meta property=og:site_name content=M2Pool><meta property=og:type content=website><meta property=og:image content=https://m2pool.com/logo.png><link rel=icon href=/favicon.ico><link rel=stylesheet href=//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css><title>M2pool - Stable leading high-yield mining pool</title><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, enx"><meta name=format-detection content="telephone=no"><meta name=apple-mobile-web-app-capable content=yes><script defer src=/js/chunk-vendors-945ce2fe.648a91a9.js></script><script defer src=/js/chunk-vendors-aacc2dbb.d317c558.js></script><script defer src=/js/chunk-vendors-bc050c32.3f2f14d2.js></script><script defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer src=/js/chunk-vendors-439af1fa.48a48f35.js></script><script defer src=/js/chunk-vendors-5c533fba.b9c00e08.js></script><script defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer src=/js/chunk-vendors-c2f7d60e.3710fdc2.js></script><script defer src=/js/chunk-vendors-89d5c698.2190b4ca.js></script><script defer src=/js/chunk-vendors-377fed06.159de137.js></script><script defer src=/js/chunk-vendors-5a805870.4cfc0ae8.js></script><script defer src=/js/chunk-vendors-cf2e0a28.c6e99da0.js></script><script defer src=/js/app-42f9d7e6.d563e0a6.js></script><script defer src=/js/app-89ec8940.a029b1cd.js></script><script defer src=/js/app-d363ae0c.3ec67189.js></script><script defer src=/js/app-5c551db8.3a30163d.js></script><script defer src=/js/app-b4c4f6ec.81923b59.js></script><script defer src=/js/app-a6ba6ead.22ec49a2.js></script><script defer src=/js/app-72600b29.533abe28.js></script><script defer src=/js/app-f035d474.34668127.js></script><script defer src=/js/app-7023e5b0.a956a90d.js></script><script defer src=/js/app-113c6c50.7fb5dfad.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/app-189e7968.e9d72c1e.css rel=stylesheet><link href=/css/app-b4c4f6ec.dbc59290.css rel=stylesheet><link href=/css/app-a6ba6ead.1697153d.css rel=stylesheet><link href=/css/app-72600b29.60a65385.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-7023e5b0.87f1eef9.css rel=stylesheet><link href=/css/app-113c6c50.20159bae.css rel=stylesheet></head><body><div id=app></div></body></html>
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=google-site-verification content=pKAZogQ0NQ6L4j9-V58WJMjm7zYCFwkJXSJzWu9UDM8><meta name=robots content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><meta name=googlebot content="index, follow"><meta name=googlebot-news content="index, follow"><meta name=bingbot content="index, follow"><link rel=alternate hreflang=zh href=https://m2pool.com/zh><link rel=alternate hreflang=en href=https://m2pool.com/en><link rel=alternate hreflang=x-default href=https://m2pool.com/en><meta property=og:title content="M2pool - Stable leading high-yield mining pool"><meta property=og:description content="M2Pool provides professional mining services, supporting multiple cryptocurrency mining"><meta property=og:url content=https://m2pool.com/en><meta property=og:site_name content=M2Pool><meta property=og:type content=website><meta property=og:image content=https://m2pool.com/logo.png><link rel=icon href=/favicon.ico><link rel=stylesheet href=//at.alicdn.com/t/c/font_4582735_7i8wfzc0art.css><title>M2pool - Stable leading high-yield mining pool</title><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, enx"><meta name=format-detection content="telephone=no"><meta name=apple-mobile-web-app-capable content=yes><script defer src=/js/chunk-vendors-945ce2fe.648a91a9.js></script><script defer src=/js/chunk-vendors-aacc2dbb.d317c558.js></script><script defer src=/js/chunk-vendors-bc050c32.3f2f14d2.js></script><script defer src=/js/chunk-vendors-3003db77.d0b93d36.js></script><script defer src=/js/chunk-vendors-9d134daf.bb668c99.js></script><script defer src=/js/chunk-vendors-439af1fa.48a48f35.js></script><script defer src=/js/chunk-vendors-5c533fba.b9c00e08.js></script><script defer src=/js/chunk-vendors-96cecd74.a7d9b845.js></script><script defer src=/js/chunk-vendors-c5c6856a.635a8cad.js></script><script defer src=/js/chunk-vendors-cca472bf.9545e49e.js></script><script defer src=/js/chunk-vendors-377fed06.79dbd1e2.js></script><script defer src=/js/chunk-vendors-0dc8c06b.8c238ff1.js></script><script defer src=/js/chunk-vendors-5fc483a3.764e837b.js></script><script defer src=/js/chunk-vendors-5a805870.4cfc0ae8.js></script><script defer src=/js/chunk-vendors-cf2e0a28.c6e99da0.js></script><script defer src=/js/app-42f9d7e6.a72a71c4.js></script><script defer src=/js/app-89ec8940.10a6eac4.js></script><script defer src=/js/app-d363ae0c.4e837441.js></script><script defer src=/js/app-5c551db8.f371968e.js></script><script defer src=/js/app-b4c4f6ec.694d520a.js></script><script defer src=/js/app-45954fd3.3eca7309.js></script><script defer src=/js/app-a6ba6ead.99f4f586.js></script><script defer src=/js/app-93e14cbe.808377ef.js></script><script defer src=/js/app-72600b29.6108bda3.js></script><script defer src=/js/app-f035d474.34668127.js></script><script defer src=/js/app-7023e5b0.a956a90d.js></script><script defer src=/js/app-113c6c50.eedc8429.js></script><link href=/css/chunk-vendors-5c533fba.6f97509c.css rel=stylesheet><link href=/css/chunk-vendors-cca472bf.3cf4fa64.css rel=stylesheet><link href=/css/app-189e7968.a2f5d347.css rel=stylesheet><link href=/css/app-b4c4f6ec.6e507abe.css rel=stylesheet><link href=/css/app-72600b29.84aa355f.css rel=stylesheet><link href=/css/app-f035d474.0348646a.css rel=stylesheet><link href=/css/app-7023e5b0.87f1eef9.css rel=stylesheet><link href=/css/app-113c6c50.ed286d28.css rel=stylesheet></head><body><div id=app></div></body></html>

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/en</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-10T03:13:18.219Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/en</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>https://m2pool.com/en/dataDisplay</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/ServiceTerms</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url><url><loc>https://m2pool.com/en/apiFile</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/rate</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.8</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/grsAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/monaAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/en/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-16T08:11:32.323Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>

Binary file not shown.

View File

@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/zh</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-10T03:13:18.212Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://m2pool.com/zh</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/dataDisplay</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/ServiceTerms</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>monthly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/apiFile</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/rate</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/nexaAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/grsAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/monaAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbsAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgbqAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/dgboAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url><url><loc>https://m2pool.com/zh/AccessMiningPool/rxdAccess</loc><lastmod>2025-07-16T08:11:32.315Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url></urlset>

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.