mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2025-05-23 19:35:24 +00:00
commit
fb9d7580ff
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
/node_modules
|
||||
/.idea
|
||||
/dist
|
||||
/dist.zip
|
||||
|
379
package-lock.json
generated
379
package-lock.json
generated
@ -12,8 +12,10 @@
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"element-plus": "^2.9.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"pinia": "^3.0.1",
|
||||
"vue": "^3.3.10",
|
||||
"vue-i18n": "^11.1.1",
|
||||
"vue3-draggable-resizable": "^1.6.5",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -35,10 +37,29 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
|
||||
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
|
||||
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.6.tgz",
|
||||
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
|
||||
"version": "7.26.10",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.10.tgz",
|
||||
"integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.26.10"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
@ -46,6 +67,18 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.26.10",
|
||||
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.26.10.tgz",
|
||||
"integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.25.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ctrl/tinycolor": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
|
||||
@ -560,9 +593,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
@ -835,49 +868,49 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.11.tgz",
|
||||
"integrity": "sha512-h97/TGWBilnLuRaj58sxNrsUU66fwdRKLOLQ9N/5iNDfp+DZhYH9Obhe0bXxhedl8fjAgpRANpiZfbgWyruQ0w==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
|
||||
"integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@vue/shared": "3.3.11",
|
||||
"@babel/parser": "^7.25.3",
|
||||
"@vue/shared": "3.5.13",
|
||||
"entities": "^4.5.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.0.2"
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.11.tgz",
|
||||
"integrity": "sha512-zoAiUIqSKqAJ81WhfPXYmFGwDRuO+loqLxvXmfUdR5fOitPoUiIeFI9cTTyv9MU5O1+ZZglJVTusWzy+wfk5hw==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
|
||||
"integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.3.11",
|
||||
"@vue/shared": "3.3.11"
|
||||
"@vue/compiler-core": "3.5.13",
|
||||
"@vue/shared": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.11.tgz",
|
||||
"integrity": "sha512-U4iqPlHO0KQeK1mrsxCN0vZzw43/lL8POxgpzcJweopmqtoYy9nljJzWDIQS3EfjiYhfdtdk9Gtgz7MRXnz3GA==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
|
||||
"integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@vue/compiler-core": "3.3.11",
|
||||
"@vue/compiler-dom": "3.3.11",
|
||||
"@vue/compiler-ssr": "3.3.11",
|
||||
"@vue/reactivity-transform": "3.3.11",
|
||||
"@vue/shared": "3.3.11",
|
||||
"@babel/parser": "^7.25.3",
|
||||
"@vue/compiler-core": "3.5.13",
|
||||
"@vue/compiler-dom": "3.5.13",
|
||||
"@vue/compiler-ssr": "3.5.13",
|
||||
"@vue/shared": "3.5.13",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.5",
|
||||
"postcss": "^8.4.32",
|
||||
"source-map-js": "^1.0.2"
|
||||
"magic-string": "^0.30.11",
|
||||
"postcss": "^8.4.48",
|
||||
"source-map-js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.11.tgz",
|
||||
"integrity": "sha512-Zd66ZwMvndxRTgVPdo+muV4Rv9n9DwQ4SSgWWKWkPFebHQfVYRrVjeygmmDmPewsHyznCNvJ2P2d6iOOhdv8Qg==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
|
||||
"integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.3.11",
|
||||
"@vue/shared": "3.3.11"
|
||||
"@vue/compiler-dom": "3.5.13",
|
||||
"@vue/shared": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/devtools-api": {
|
||||
@ -885,6 +918,28 @@
|
||||
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
|
||||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
|
||||
},
|
||||
"node_modules/@vue/devtools-kit": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
|
||||
"integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-shared": "^7.7.2",
|
||||
"birpc": "^0.2.19",
|
||||
"hookable": "^5.5.3",
|
||||
"mitt": "^3.0.1",
|
||||
"perfect-debounce": "^1.0.0",
|
||||
"speakingurl": "^14.0.1",
|
||||
"superjson": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/devtools-shared": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
|
||||
"integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
|
||||
"dependencies": {
|
||||
"rfdc": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/eslint-config-prettier": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/eslint-config-prettier/-/eslint-config-prettier-8.0.0.tgz",
|
||||
@ -900,60 +955,49 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.11.tgz",
|
||||
"integrity": "sha512-D5tcw091f0nuu+hXq5XANofD0OXnBmaRqMYl5B3fCR+mX+cXJIGNw/VNawBqkjLNWETrFW0i+xH9NvDbTPVh7g==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
|
||||
"integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.3.11"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity-transform": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.11.tgz",
|
||||
"integrity": "sha512-fPGjH0wqJo68A0wQ1k158utDq/cRyZNlFoxGwNScE28aUFOKFEnCBsvyD8jHn+0kd0UKVpuGuaZEQ6r9FJRqCg==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@vue/compiler-core": "3.3.11",
|
||||
"@vue/shared": "3.3.11",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.5"
|
||||
"@vue/shared": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.11.tgz",
|
||||
"integrity": "sha512-g9ztHGwEbS5RyWaOpXuyIVFTschclnwhqEbdy5AwGhYOgc7m/q3NFwr50MirZwTTzX55JY8pSkeib9BX04NIpw==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
|
||||
"integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.3.11",
|
||||
"@vue/shared": "3.3.11"
|
||||
"@vue/reactivity": "3.5.13",
|
||||
"@vue/shared": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.11.tgz",
|
||||
"integrity": "sha512-OlhtV1PVpbgk+I2zl+Y5rQtDNcCDs12rsRg71XwaA2/Rbllw6mBLMi57VOn8G0AjOJ4Mdb4k56V37+g8ukShpQ==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
|
||||
"integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
|
||||
"dependencies": {
|
||||
"@vue/runtime-core": "3.3.11",
|
||||
"@vue/shared": "3.3.11",
|
||||
"csstype": "^3.1.2"
|
||||
"@vue/reactivity": "3.5.13",
|
||||
"@vue/runtime-core": "3.5.13",
|
||||
"@vue/shared": "3.5.13",
|
||||
"csstype": "^3.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.11.tgz",
|
||||
"integrity": "sha512-AIWk0VwwxCAm4wqtJyxBylRTXSy1wCLOKbWxHaHiu14wjsNYtiRCSgVuqEPVuDpErOlRdNnuRgipQfXRLjLN5A==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
|
||||
"integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.3.11",
|
||||
"@vue/shared": "3.3.11"
|
||||
"@vue/compiler-ssr": "3.5.13",
|
||||
"@vue/shared": "3.5.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.3.11"
|
||||
"vue": "3.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.11.tgz",
|
||||
"integrity": "sha512-u2G8ZQ9IhMWTMXaWqZycnK4UthG1fA238CD+DP4Dm4WJi5hdUKKLg0RMRaRpDPNMdkTwIDkp7WtD0Rd9BH9fLw=="
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz",
|
||||
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ=="
|
||||
},
|
||||
"node_modules/@vueup/vue-quill": {
|
||||
"version": "1.2.0",
|
||||
@ -1123,6 +1167,14 @@
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/birpc": {
|
||||
"version": "0.2.19",
|
||||
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
|
||||
"integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
|
||||
@ -1273,6 +1325,20 @@
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/copy-anything": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
|
||||
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
|
||||
"dependencies": {
|
||||
"is-what": "^4.1.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
@ -1478,6 +1544,17 @@
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
@ -2092,6 +2169,11 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hookable": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
|
||||
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
|
||||
},
|
||||
"node_modules/html2canvas": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||
@ -2282,6 +2364,17 @@
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-what": {
|
||||
"version": "4.1.16",
|
||||
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
|
||||
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
|
||||
"engines": {
|
||||
"node": ">=12.13"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mesqueeb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-wsl": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||
@ -2426,14 +2519,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.5",
|
||||
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.5.tgz",
|
||||
"integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==",
|
||||
"version": "0.30.17",
|
||||
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
|
||||
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
@ -2498,6 +2588,11 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mitt": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
|
||||
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
|
||||
@ -2505,9 +2600,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"version": "3.3.9",
|
||||
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.9.tgz",
|
||||
"integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@ -2700,10 +2801,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"node_modules/perfect-debounce": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
"resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
||||
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
@ -2714,14 +2820,56 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.32",
|
||||
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.32.tgz",
|
||||
"integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==",
|
||||
"node_modules/pinia": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/pinia/-/pinia-3.0.1.tgz",
|
||||
"integrity": "sha512-WXglsDzztOTH6IfcJ99ltYZin2mY8XZCXujkYWVIJlBjqsP6ST7zw+Aarh63E1cDVYeyUcPCxPHzJpEOmzB6Wg==",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.7",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
"@vue/devtools-api": "^7.7.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/posva"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.4.4",
|
||||
"vue": "^2.7.0 || ^3.5.11"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia/node_modules/@vue/devtools-api": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
|
||||
"integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-kit": "^7.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
|
||||
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.8",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
@ -2872,6 +3020,11 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
|
||||
@ -3092,9 +3245,17 @@
|
||||
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/speakingurl": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
|
||||
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -3129,6 +3290,17 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/superjson": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
|
||||
"integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
|
||||
"dependencies": {
|
||||
"copy-anything": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@ -3301,15 +3473,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.11.tgz",
|
||||
"integrity": "sha512-d4oBctG92CRO1cQfVBZp6WJAs0n8AK4Xf5fNjQCBeKCvMI1efGQ5E3Alt1slFJS9fZuPcFoiAiqFvQlv1X7t/w==",
|
||||
"version": "3.5.13",
|
||||
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
|
||||
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.3.11",
|
||||
"@vue/compiler-sfc": "3.3.11",
|
||||
"@vue/runtime-dom": "3.3.11",
|
||||
"@vue/server-renderer": "3.3.11",
|
||||
"@vue/shared": "3.3.11"
|
||||
"@vue/compiler-dom": "3.5.13",
|
||||
"@vue/compiler-sfc": "3.5.13",
|
||||
"@vue/runtime-dom": "3.5.13",
|
||||
"@vue/server-renderer": "3.5.13",
|
||||
"@vue/shared": "3.5.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
@ -3360,6 +3532,11 @@
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue3-draggable-resizable": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmmirror.com/vue3-draggable-resizable/-/vue3-draggable-resizable-1.6.5.tgz",
|
||||
"integrity": "sha512-31142E31fGNnq3HKqvmFLSsqIbhck7TyGuQWhUKrDw6DOcGAuRx4ddRjaxvT6fe7dgeKH53qAh+i0ZlWtPLl2g=="
|
||||
},
|
||||
"node_modules/vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
|
@ -15,8 +15,10 @@
|
||||
"@vueup/vue-quill": "^1.2.0",
|
||||
"element-plus": "^2.9.1",
|
||||
"html2canvas": "^1.4.1",
|
||||
"pinia": "^3.0.1",
|
||||
"vue": "^3.3.10",
|
||||
"vue-i18n": "^11.1.1",
|
||||
"vue3-draggable-resizable": "^1.6.5",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
BIN
public/assets/Other/Contact.png
Normal file
BIN
public/assets/Other/Contact.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
159
src/App.vue
159
src/App.vue
@ -1,40 +1,157 @@
|
||||
<script setup>
|
||||
import Yys from './components/Yys.vue'
|
||||
import Toolbar from './components/Toolbar.vue'
|
||||
import {ref} from "vue";
|
||||
<script setup lang="ts">
|
||||
import Yys from './components/Yys.vue';
|
||||
import Toolbar from './components/Toolbar.vue';
|
||||
import ProjectExplorer from './components/ProjectExplorer.vue';
|
||||
import { computed, ref, onMounted, onUnmounted } from "vue";
|
||||
import { useFilesStore } from "@/ts/files";
|
||||
import Vue3DraggableResizable from 'vue3-draggable-resizable';
|
||||
import { TabPaneName, TabsPaneContext } from "element-plus";
|
||||
|
||||
const filesStore = useFilesStore();
|
||||
|
||||
const yysRef = ref(null);
|
||||
const width = ref('100%');
|
||||
const height = ref('100vh');
|
||||
const toolbarHeight = 48; // 工具栏的高度
|
||||
const windowHeight = ref(window.innerHeight);
|
||||
const contentHeight = computed(() => `${windowHeight.value - toolbarHeight}px`);
|
||||
|
||||
const onHandleInport = (file) => {
|
||||
yysRef.value.importGroups(file);
|
||||
const onResizing = (x, y, width, height) => {
|
||||
width.value = width;
|
||||
height.value = height;
|
||||
};
|
||||
|
||||
const onHandleExport = () => {
|
||||
yysRef.value.exportGroups();
|
||||
const element = ref({
|
||||
x: 400,
|
||||
y: 20,
|
||||
width: 1080,
|
||||
height: windowHeight.value - toolbarHeight,
|
||||
isActive: false,
|
||||
});
|
||||
|
||||
const handleTabsEdit = (
|
||||
targetName: String | undefined,
|
||||
action: 'remove' | 'add'
|
||||
) => {
|
||||
if (action === 'remove') {
|
||||
filesStore.closeTab(targetName);
|
||||
} else if (action === 'add') {
|
||||
const newFileName = `File ${filesStore.fileList.length + 1}`;
|
||||
|
||||
filesStore.addFile({
|
||||
label: newFileName,
|
||||
name: newFileName,
|
||||
visible: true,
|
||||
type:'PVE',
|
||||
groups:[
|
||||
{
|
||||
shortDescription: " ",
|
||||
groupInfo: [{}, {}, {}, {}, {}],
|
||||
details: ''
|
||||
},
|
||||
{
|
||||
shortDescription: '',
|
||||
groupInfo: [{}, {}, {}, {}, {}],
|
||||
details: ''
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', () => {
|
||||
windowHeight.value = window.innerHeight;
|
||||
});
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', () => {
|
||||
windowHeight.value = window.innerHeight;
|
||||
});
|
||||
});
|
||||
|
||||
const activeFileGroups = computed(() => {
|
||||
const activeFile = filesStore.fileList.find(file => file.name === filesStore.activeFile);
|
||||
return activeFile ? activeFile.groups : [];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main id="main-container">
|
||||
<!-- 添加工具栏 -->
|
||||
<Toolbar title="yys-editor" username="示例用户" data-html2canvas-ignore="true" @handleExport="onHandleExport" @handleImport="onHandleInport"/>
|
||||
<!-- 添加 Watermark 组件 -->
|
||||
<Yys ref="yysRef"/>
|
||||
<div class="container">
|
||||
<!-- 工具栏 -->
|
||||
<Toolbar title="yys-editor" username="示例用户"/>
|
||||
<!-- 侧边栏和工作区 -->
|
||||
<div class="main-content">
|
||||
<!-- 侧边栏 -->
|
||||
<aside class="sidebar">
|
||||
<ProjectExplorer :allFiles="filesStore.fileList" />
|
||||
</aside>
|
||||
|
||||
</main>
|
||||
<!-- 工作区 -->
|
||||
<div class="workspace">
|
||||
<el-tabs
|
||||
v-model="filesStore.activeFile"
|
||||
type="card"
|
||||
class="demo-tabs"
|
||||
editable
|
||||
@edit="handleTabsEdit"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="(file, index) in filesStore.visibleFiles"
|
||||
:key="`${file.name}-${filesStore.activeFile}`"
|
||||
:label="file.label"
|
||||
:name="file.name.toString()"
|
||||
>
|
||||
<main id="main-container" :style="{ height: contentHeight, overflow: 'auto' }">
|
||||
<Yys :groups="activeFileGroups"/>
|
||||
</main>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* 确保 #main-container 具有相对定位 */
|
||||
#main-container {
|
||||
margin-top: 48px; /* 与工具栏高度相同 */
|
||||
position: relative;
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
height: 48px; /* 与 toolbarHeight 一致 */
|
||||
flex-shrink: 0; /* 防止 Toolbar 被压缩 */
|
||||
background-color: #fff; /* 添加背景色以便观察 */
|
||||
z-index: 1; /* 确保 Toolbar 在上层 */
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex: 1; /* 占据剩余空间 */
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
margin-top: 48px; /* 确保 main-content 在 Toolbar 下方 */
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 20%; /* 侧边栏宽度 */
|
||||
background-color: #f0f0f0; /* 背景色 */
|
||||
flex-shrink: 0; /* 防止侧边栏被压缩 */
|
||||
overflow-y: auto; /* 允许侧边栏内容滚动 */
|
||||
}
|
||||
|
||||
.workspace {
|
||||
//flex: 1; /* 占据剩余空间 */
|
||||
overflow: hidden; /* 防止内容溢出 */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
position: relative;
|
||||
height: 100%; /* 确保内容区域占满父容器 */
|
||||
overflow-y: auto; /* 允许内容滚动 */
|
||||
min-height: 100vh; /* 允许容器扩展 */
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
|
||||
}
|
||||
|
||||
/* 如果 Yys 组件需要特定的高度或布局,可以根据需要调整 */
|
||||
</style>
|
106
src/components/ProjectExplorer.vue
Normal file
106
src/components/ProjectExplorer.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="project-explorer">
|
||||
<el-tree
|
||||
:data="allFiles"
|
||||
:props="defaultProps"
|
||||
@node-click="handleNodeClick"
|
||||
node-key="name"
|
||||
default-expand-all
|
||||
:expand-on-click-node="false"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="custom-tree-node">
|
||||
<span>{{ node.label }}</span>
|
||||
<div>
|
||||
<el-dropdown>
|
||||
<el-button
|
||||
style="margin-left: 4px"
|
||||
icon="MoreFilled"
|
||||
link
|
||||
/>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="() => renameFile(data)">Rename</el-dropdown-item>
|
||||
<el-dropdown-item @click="() => deleteFile(data)">Delete</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {defineProps, defineEmits, ref} from 'vue';
|
||||
import {useFilesStore} from "@/ts/files";
|
||||
import {ElTree, ElButton, ElDropdownMenu, ElDropdownItem} from 'element-plus';
|
||||
|
||||
const filesStore = useFilesStore();
|
||||
|
||||
const props = defineProps({
|
||||
allFiles: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
};
|
||||
|
||||
const visibleDropdown = ref(false);
|
||||
const dropdownLeft = ref(0);
|
||||
const dropdownTop = ref(0);
|
||||
const selectedData = ref(null);
|
||||
|
||||
const handleNodeClick = (data) => {
|
||||
filesStore.setActiveFile(data.name);
|
||||
filesStore.setVisible(data.name, true);
|
||||
};
|
||||
|
||||
const showOptions = (node, data) => {
|
||||
visibleDropdown.value = true;
|
||||
dropdownLeft.value = node.$el.offsetLeft + 20;
|
||||
dropdownTop.value = node.$el.offsetTop + 20;
|
||||
selectedData.value = data;
|
||||
};
|
||||
|
||||
const hideDropdown = () => {
|
||||
visibleDropdown.value = false;
|
||||
};
|
||||
|
||||
document.addEventListener('click', hideDropdown);
|
||||
|
||||
const deleteFile = (data) => {
|
||||
filesStore.deleteFile(data.name);
|
||||
hideDropdown();
|
||||
};
|
||||
|
||||
const renameFile = (data) => {
|
||||
const newName = prompt("Enter new name:", data.label);
|
||||
if (newName && newName !== data.label) {
|
||||
filesStore.renameFile(data.name, newName);
|
||||
}
|
||||
hideDropdown();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.project-explorer {
|
||||
height: 50%; /* 占据侧边栏的一半 */
|
||||
min-height: 400px;
|
||||
overflow-y: auto; /* 允许内容滚动 */
|
||||
}
|
||||
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
</style>
|
@ -130,6 +130,7 @@ import YuhunSelect from "@/components/YuhunSelect.vue";
|
||||
import {useI18n} from 'vue-i18n'
|
||||
// import YuhunSelect from "./YuhunSelect.vue";
|
||||
|
||||
|
||||
// 获取当前的 i18n 实例
|
||||
const {t} = useI18n()
|
||||
|
||||
@ -339,7 +340,7 @@ const cancel = () => {
|
||||
|
||||
const confirm = () => {
|
||||
shikigami.value.edit = true
|
||||
emit('updateProperty', JSON.parse(JSON.stringify(shikigami.value)))
|
||||
emit('updateProperty', shikigami.value);
|
||||
resetData()
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,37 @@
|
||||
t('setWatermark')
|
||||
}}
|
||||
</el-button>
|
||||
<!-- 新增的按钮 -->
|
||||
<el-button type="info" @click="showUpdateLog">更新日志</el-button>
|
||||
<el-button type="warning" @click="showFeedbackForm">问题反馈</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 更新日志对话框 -->
|
||||
<el-dialog v-model="state.showUpdateLogDialog" title="更新日志" width="60%">
|
||||
<ul>
|
||||
<li v-for="(log, index) in updateLogs" :key="index">
|
||||
<strong>版本 {{ log.version }} - {{ log.date }}</strong>
|
||||
<ul>
|
||||
<li v-for="(change, idx) in log.changes" :key="idx">{{ change }}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 更新日志对话框 -->
|
||||
<el-dialog v-model="state.showFeedbackFormDialog" title="更新日志" width="60%">
|
||||
<span style="font-size: 24px;">备注阴阳师</span>
|
||||
<br/>
|
||||
<img src="/assets/Other/Contact.png"
|
||||
style="cursor: pointer; vertical-align: bottom; width: 200px; height: auto;"/>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 预览弹窗 -->
|
||||
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" height="80%" :before-close="handleClose">
|
||||
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" height="80%"
|
||||
:before-close="handleClose">
|
||||
<div style="max-height: 500px; overflow-y: auto;">
|
||||
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
|
||||
</div>
|
||||
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="state.previewVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="downloadImage">下 载</el-button>
|
||||
@ -55,24 +78,45 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {ref, reactive} from 'vue';
|
||||
import html2canvas from "html2canvas";
|
||||
import {useI18n} from 'vue-i18n';
|
||||
import updateLogs from "../data/updateLog.json"
|
||||
import {useFilesStore} from "@/ts/files";
|
||||
|
||||
const filesStore = useFilesStore();
|
||||
|
||||
// 获取当前的 i18n 实例
|
||||
const {t} = useI18n();
|
||||
const emit = defineEmits(['handleExport', 'handleImport'])
|
||||
|
||||
// 定义响应式数据
|
||||
const state = reactive({
|
||||
previewImage: null, // 用于存储预览图像的数据URL
|
||||
previewVisible: false, // 控制预览弹窗的显示状态
|
||||
showWatermarkDialog: false, // 控制水印设置弹窗的显示状态
|
||||
showWatermarkDialog: false, // 控制水印设置弹窗的显示状态,
|
||||
showUpdateLogDialog: false, // 控制更新日志对话框的显示状态
|
||||
showFeedbackFormDialog: false, // 控制反馈表单对话框的显示状态
|
||||
});
|
||||
|
||||
|
||||
const showUpdateLog = () => {
|
||||
state.showUpdateLogDialog = !state.showUpdateLogDialog;
|
||||
};
|
||||
|
||||
const showFeedbackForm = () => {
|
||||
state.showFeedbackFormDialog = !state.showFeedbackFormDialog;
|
||||
};
|
||||
|
||||
const handleExport = () => {
|
||||
emit('handleExport');
|
||||
const dataStr = JSON.stringify(filesStore.fileList, null, 2);
|
||||
const blob = new Blob([dataStr], { type: 'application/json;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'files.json';
|
||||
link.click();
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
const handleImport = () => {
|
||||
@ -81,12 +125,34 @@ const handleImport = () => {
|
||||
input.accept = '.json';
|
||||
input.onchange = (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (file) emit('handleImport', file);
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const data = JSON.parse(e.target.result as string);
|
||||
if (data[0].visible === true) {
|
||||
// 新版本格式:直接替换 fileList
|
||||
filesStore.$patch({ fileList: data });
|
||||
} else {
|
||||
// 旧版本格式:仅包含 groups 数组
|
||||
const newFile = {
|
||||
label: `File ${filesStore.fileList.length + 1}`,
|
||||
name: String(filesStore.fileList.length + 1),
|
||||
visible: true,
|
||||
groups: data
|
||||
};
|
||||
filesStore.addFile(newFile);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to import file', error);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
};
|
||||
|
||||
|
||||
const watermark = reactive({
|
||||
text: '示例水印',
|
||||
fontSize: 30,
|
||||
@ -150,9 +216,8 @@ function calculateVisualHeight(selector) {
|
||||
return rows.reduce((sum, row) => sum + row.maxHeight, 0);
|
||||
}
|
||||
|
||||
|
||||
const ignoreElements = (element) => {
|
||||
return element.classList.contains('ql-toolbar');
|
||||
return element.classList.contains('ql-toolbar') || element.classList.contains('el-tabs__header');
|
||||
};
|
||||
|
||||
const prepareCapture = async () => {
|
||||
@ -163,19 +228,34 @@ const prepareCapture = async () => {
|
||||
style.textContent = `.ql-container.ql-snow { border: none !important; }`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// 获取目标元素
|
||||
const element = document.querySelector('#main-container');
|
||||
if (!element) {
|
||||
console.error('Element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存原始 overflow 样式
|
||||
const originalOverflow = element.style.overflow;
|
||||
|
||||
try {
|
||||
const element = document.querySelector('#main-container');
|
||||
// 临时隐藏 overflow 样式
|
||||
element.style.overflow = 'visible';
|
||||
|
||||
// 计算需要忽略的元素高度
|
||||
let totalHeight = calculateVisualHeight('[data-html2canvas-ignore]') + calculateVisualHeight('.ql-toolbar');
|
||||
console.log('所有携带指定属性的元素高度之和:', totalHeight);
|
||||
if (!element) {
|
||||
console.error('Element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('主元素宽度', element.scrollWidth);
|
||||
console.log('主元素高度', element.scrollHeight);
|
||||
|
||||
// 1. 生成原始截图
|
||||
const canvas = await html2canvas(element, {
|
||||
ignoreElements: ignoreElements,
|
||||
height: element.scrollHeight - totalHeight
|
||||
scrollX: 0,
|
||||
scrollY: 0,
|
||||
width: element.scrollWidth,
|
||||
height: element.scrollHeight - totalHeight,
|
||||
});
|
||||
|
||||
// 2. 创建新Canvas添加水印
|
||||
@ -220,12 +300,16 @@ const prepareCapture = async () => {
|
||||
}
|
||||
|
||||
ctx.restore(); // 恢复原始状态
|
||||
|
||||
// 3. 存储带水印的图片
|
||||
state.previewImage = watermarkedCanvas.toDataURL();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Capture failed', error);
|
||||
} finally {
|
||||
// 恢复原始 overflow 样式
|
||||
element.style.overflow = originalOverflow;
|
||||
|
||||
// 移除临时样式
|
||||
document.head.removeChild(style);
|
||||
}
|
||||
};
|
||||
@ -254,7 +338,6 @@ const handleClose = (done) => {
|
||||
right: 0;
|
||||
height: 48px;
|
||||
background: #f8f8f8;
|
||||
//border-bottom: 1px solid #eee; display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
z-index: 100;
|
||||
|
@ -14,16 +14,16 @@
|
||||
/>
|
||||
|
||||
|
||||
<draggable :list="state.groups" item-key="group" style="display: flex; flex-direction: column; width: 100%;"
|
||||
<draggable :list="groups" item-key="group" style="display: flex; flex-direction: column; width: 100%;"
|
||||
handle=".drag-handle">
|
||||
|
||||
|
||||
<template #item="{ element: group, index: groupIndex }">
|
||||
<template class="group" #item="{ element: group, index: groupIndex }">
|
||||
<el-row :span="24">
|
||||
<div>
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between;" data-html2canvas-ignore="true">
|
||||
<div>
|
||||
<div class="group-item">
|
||||
<div class="group-header">
|
||||
<div class="group-opt" data-html2canvas-ignore="true">
|
||||
<div class="opt-left">
|
||||
<el-button type="primary" icon="CopyDocument" @click="copy(group.shortDescription)">{{ t('Copy') }}
|
||||
</el-button>
|
||||
<el-button type="primary" icon="Document" @click="paste(groupIndex,'shortDescription')">{{
|
||||
@ -31,7 +31,7 @@
|
||||
}}
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<div class="opt-right">
|
||||
<el-button class="drag-handle" type="primary" icon="Rank" circle></el-button>
|
||||
<el-button type="primary" icon="Plus" circle @click="addGroup"></el-button>
|
||||
<el-button type="danger" icon="Delete" circle @click="removeGroup(groupIndex)"></el-button>
|
||||
@ -40,20 +40,18 @@
|
||||
<QuillEditor v-model:content="group.shortDescription" contentType="html" theme="snow"
|
||||
:toolbar="toolbarOptions"/>
|
||||
</div>
|
||||
<div>
|
||||
<draggable :list="group.groupInfo" item-key="name" style="display: flex; flex-direction: row; width: 20%;">
|
||||
<div class="group-body">
|
||||
<draggable :list="group.groupInfo" item-key="name" class="body-content">
|
||||
<template #item="{element : position, index:positionIndex}">
|
||||
<div>
|
||||
<el-col>
|
||||
<el-card shadow="never"
|
||||
:body-style="{ display: 'flex', 'flex-direction': 'column', 'justify-content': 'center', 'align-items': 'center' }">
|
||||
|
||||
<div data-html2canvas-ignore="true">
|
||||
<el-card class="group-card" shadow="never">
|
||||
<div class="opt-btn" data-html2canvas-ignore="true">
|
||||
<!-- Add delete button here -->
|
||||
<el-button type="danger" icon="Delete" circle @click="removeGroupElement(groupIndex, positionIndex)"/>
|
||||
<el-button type="primary" icon="Plus" circle @click="addGroupElement(groupIndex)"/>
|
||||
</div>
|
||||
<div style="position: relative; display: inline-block;">
|
||||
<div class="avatar-container">
|
||||
<!-- 头像图片 -->
|
||||
<img :src="position.avatar || '/assets/Shikigami/default.png'"
|
||||
style="cursor: pointer; vertical-align: bottom;"
|
||||
@ -61,15 +59,10 @@
|
||||
@click="editShikigami(groupIndex, positionIndex)"/>
|
||||
|
||||
<!-- 文字图层 -->
|
||||
<span v-if="position.properties"
|
||||
style="position: absolute; bottom: 0; left: 50%; transform: translateX(-50%) translateY(50%);
|
||||
font-size: 24px; color: white; text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black;
|
||||
white-space: nowrap; padding: 0 8px; margin: 0; display: flex; align-items: center; justify-content: center;">
|
||||
{{ position.properties.levelRequired }}级 {{ position.properties.skillRequired.join('') }}
|
||||
</span>
|
||||
<span v-if="position.properties">{{ position.properties.levelRequired }}级 {{ position.properties.skillRequired.join('') }}</span>
|
||||
</div>
|
||||
<div style="padding: 14px; width: 120px;">
|
||||
|
||||
<div class="property-wrap">
|
||||
<div style="display: flex; justify-content: center;" data-html2canvas-ignore="true">
|
||||
<span>{{ position.name || "" }}</span>
|
||||
</div>
|
||||
@ -99,10 +92,9 @@
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<div data-html2canvas-ignore="true">
|
||||
<div class="group-footer">
|
||||
<div class="opt-left" data-html2canvas-ignore="true">
|
||||
<el-button type="primary" icon="CopyDocument" @click="copy(group.details)">{{ t('Copy') }}</el-button>
|
||||
<el-button type="primary" icon="Document" @click="paste(groupIndex,'details')">{{
|
||||
t('Paste')
|
||||
@ -111,22 +103,13 @@
|
||||
</div>
|
||||
<QuillEditor v-model:content="group.details" contentType="html" theme="snow" :toolbar="toolbarOptions"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<!-- </el-row>-->
|
||||
</draggable>
|
||||
<div style="margin: 20px">
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {ref, reactive, toRefs} from 'vue';
|
||||
import draggable from 'vuedraggable';
|
||||
import ShikigamiSelect from './ShikigamiSelect.vue';
|
||||
@ -138,24 +121,17 @@ import '@vueup/vue-quill/dist/vue-quill.snow.css' // 引入样式文件
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import shikigamiData from '../data/Shikigami.json';
|
||||
import _ from 'lodash';
|
||||
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||
import { useGlobalMessage } from '../ts/useGlobalMessage'; // 引入全局消息通知工具
|
||||
const props = defineProps<{
|
||||
groups: any[];
|
||||
}>();
|
||||
|
||||
const dialogTableVisible = ref(false)
|
||||
// 定义响应式数据
|
||||
const state = reactive({
|
||||
showSelectShikigami: false,
|
||||
showProperty: false,
|
||||
groups: [
|
||||
{
|
||||
shortDescription: '',
|
||||
groupInfo: [{}, {}, {}, {}, {}],
|
||||
details: ''
|
||||
},
|
||||
{
|
||||
shortDescription: '',
|
||||
groupInfo: [{}, {}, {}, {}, {}],
|
||||
details: ''
|
||||
},
|
||||
],
|
||||
groupIndex: 0,
|
||||
positionIndex: 0,
|
||||
currentShikigami: {},
|
||||
@ -165,6 +141,7 @@ const state = reactive({
|
||||
|
||||
const clipboard = ref('');
|
||||
|
||||
const { showMessage } = useGlobalMessage();
|
||||
|
||||
// 获取当前的 i18n 实例
|
||||
const {t} = useI18n()
|
||||
@ -175,9 +152,9 @@ const copy = (str) => {
|
||||
|
||||
const paste = (groupIndex, type) => {
|
||||
if ('shortDescription' == type)
|
||||
state.groups[groupIndex].shortDescription = clipboard.value
|
||||
props.groups[groupIndex].shortDescription = clipboard.value
|
||||
else if ('details' == type)
|
||||
state.groups[groupIndex].details = clipboard.value
|
||||
props.groups[groupIndex].details = clipboard.value
|
||||
}
|
||||
|
||||
// 定义工具栏选项
|
||||
@ -211,23 +188,23 @@ const editShikigami = (groupIndex, positionIndex) => {
|
||||
state.showSelectShikigami = true;
|
||||
state.groupIndex = groupIndex;
|
||||
state.positionIndex = positionIndex;
|
||||
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
||||
state.currentShikigami = props.groups[groupIndex].groupInfo[positionIndex];
|
||||
};
|
||||
|
||||
const updateShikigami = (shikigami) => {
|
||||
console.log("parent====> ", shikigami);
|
||||
state.showSelectShikigami = false;
|
||||
|
||||
const oldProperties = state.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
||||
state.groups[state.groupIndex].groupInfo[state.positionIndex] = _.cloneDeep(shikigami);
|
||||
state.groups[state.groupIndex].groupInfo[state.positionIndex].properties = oldProperties;
|
||||
const oldProperties = props.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
||||
props.groups[state.groupIndex].groupInfo[state.positionIndex] = _.cloneDeep(shikigami);
|
||||
props.groups[state.groupIndex].groupInfo[state.positionIndex].properties = oldProperties;
|
||||
};
|
||||
|
||||
const editProperty = (groupIndex, positionIndex) => {
|
||||
state.showProperty = true;
|
||||
state.groupIndex = groupIndex;
|
||||
state.positionIndex = positionIndex;
|
||||
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
||||
state.currentShikigami = props.groups[groupIndex].groupInfo[positionIndex];
|
||||
};
|
||||
|
||||
const closeProperty = () => {
|
||||
@ -238,19 +215,50 @@ const closeProperty = () => {
|
||||
const updateProperty = (property) => {
|
||||
state.showProperty = false;
|
||||
state.currentShikigami = {};
|
||||
state.groups[state.groupIndex].groupInfo[state.positionIndex].properties = _.cloneDeep(property);
|
||||
props.groups[state.groupIndex].groupInfo[state.positionIndex].properties = _.cloneDeep(property);
|
||||
};
|
||||
|
||||
const removeGroupElement = (groupIndex, positionIndex) => {
|
||||
state.groups[groupIndex].groupInfo.splice(positionIndex, 1);
|
||||
const removeGroupElement = async (groupIndex: number, positionIndex: number) => {
|
||||
const group = props.groups[groupIndex];
|
||||
|
||||
if (group.groupInfo.length === 1) {
|
||||
showMessage('warning', '无法删除');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除此元素吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
});
|
||||
group.groupInfo.splice(positionIndex, 1);
|
||||
showMessage('success', '删除成功!');
|
||||
} catch (error) {
|
||||
showMessage('info', '已取消删除');
|
||||
}
|
||||
};
|
||||
|
||||
const removeGroup = (groupIndex) => {
|
||||
state.groups.splice(groupIndex, 1);
|
||||
};
|
||||
const removeGroup = async (groupIndex: number) => {
|
||||
if (props.groups.length === 1) {
|
||||
showMessage('warning', '无法删除最后一个队伍');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要删除此组吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
});
|
||||
props.groups.splice(groupIndex, 1);
|
||||
showMessage('success', '删除成功!');
|
||||
} catch (error) {
|
||||
showMessage('info', '已取消删除');
|
||||
}
|
||||
};
|
||||
const addGroup = () => {
|
||||
state.groups.push({
|
||||
props.groups.push({
|
||||
shortDescription: '',
|
||||
groupInfo: [{}, {}, {}, {}, {}],
|
||||
details: ''
|
||||
@ -258,12 +266,12 @@ const addGroup = () => {
|
||||
};
|
||||
|
||||
const addGroupElement = (groupIndex) => {
|
||||
state.groups[groupIndex].groupInfo.push({});
|
||||
props.groups[groupIndex].groupInfo.push({});
|
||||
};
|
||||
|
||||
|
||||
const exportGroups = () => {
|
||||
const dataStr = JSON.stringify(state.groups, null, 2);
|
||||
const dataStr = JSON.stringify(props.groups, null, 2);
|
||||
const blob = new Blob([dataStr], {type: 'application/json'});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
@ -314,7 +322,7 @@ const importGroups = (file) => {
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const importedData = JSON.parse(e.target.result);
|
||||
state.groups = importedData;
|
||||
props.groups = importedData;
|
||||
ElMessage.success('导入成功');
|
||||
} catch (error) {
|
||||
ElMessage.error('文件格式错误');
|
||||
@ -369,5 +377,76 @@ defineExpose({
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.group-header {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.group-opt {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.group-body {
|
||||
padding: 20px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.body-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.group-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.avatar-container span {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(50%);
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black;
|
||||
white-space: nowrap;
|
||||
padding: 0 8px;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.opt-btn {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.property-wrap {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
/* 当鼠标悬停在容器上时显示按钮 */
|
||||
.group-card:hover .opt-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group-footer {
|
||||
margin: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
18
src/data/updateLog.json
Normal file
18
src/data/updateLog.json
Normal file
@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"date": "2025-03-18",
|
||||
"changes": [
|
||||
"修复了相同式神不能正确设置属性的问题",
|
||||
"支持了多文件编辑,重命名,删除效果",
|
||||
"增加了最后一个文件/队伍/式神的删除限制"
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"date": "2025-03-09",
|
||||
"changes": [
|
||||
"首次发布"
|
||||
]
|
||||
}
|
||||
]
|
29
src/main.js
29
src/main.js
@ -1,24 +1,28 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
import ElementPlus from 'element-plus'
|
||||
import ElementPlus, {ElMessageBox} from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
|
||||
import Vue3DraggableResizable from 'vue3-draggable-resizable'
|
||||
// default styles
|
||||
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
|
||||
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
// 引入语言文件
|
||||
import zh from './locales/zh.json'
|
||||
import ja from './locales/ja.json'
|
||||
|
||||
import { createPinia } from 'pinia' // 导入 Pinia
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
|
||||
|
||||
// 获取用户的首选语言
|
||||
const userLanguage = navigator.language
|
||||
|
||||
@ -40,10 +44,19 @@ const i18n = createI18n({
|
||||
},
|
||||
})
|
||||
|
||||
app.use(i18n)
|
||||
app.use(ElementPlus)
|
||||
app.mount('#app')
|
||||
|
||||
|
||||
// 设置ElMessageBox的默认配置
|
||||
ElMessageBox.defaults = {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning', // 默认类型为警告
|
||||
center: true, // 文字居中
|
||||
customClass: 'my-message-box', // 自定义类名,用于CSS样式覆盖
|
||||
};
|
||||
|
||||
const pinia = createPinia() // 创建 Pinia 实例
|
||||
|
||||
app.use(pinia) // 使用 Pinia
|
||||
.use(i18n)
|
||||
.use(ElementPlus)
|
||||
.use(Vue3DraggableResizable)
|
||||
.mount('#app')
|
252
src/ts/files.ts
Normal file
252
src/ts/files.ts
Normal file
@ -0,0 +1,252 @@
|
||||
import {defineStore} from 'pinia';
|
||||
import {ElMessageBox} from "element-plus";
|
||||
import {useGlobalMessage} from "./useGlobalMessage";
|
||||
|
||||
const { showMessage } = useGlobalMessage();
|
||||
export const useFilesStore = defineStore('files', {
|
||||
state: () => ({
|
||||
fileList: [
|
||||
{
|
||||
"label": "Welcome",
|
||||
"name": "1",
|
||||
"type":"PVE",
|
||||
"visible": true,
|
||||
"groups": [
|
||||
{
|
||||
"shortDescription": "<h1>鬼灵歌姬</h1><h2><em>这是一个演示项目,用于测试显示6个式神的对齐效果</em></h2>",
|
||||
"groupInfo": [
|
||||
{
|
||||
"avatar": "/assets/Shikigami/sp/372.png",
|
||||
"name": "因幡辉夜姬",
|
||||
"rarity": "SP"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/356.png",
|
||||
"name": "千姬",
|
||||
"rarity": "SSR"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/sp/554.png",
|
||||
"name": "纺愿缘结神",
|
||||
"rarity": "SP"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/556.png",
|
||||
"name": "天照",
|
||||
"rarity": "SSR"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/557.png",
|
||||
"name": "伊邪那美",
|
||||
"rarity": "SSR"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/sp/367.png",
|
||||
"name": "绘世花鸟卷",
|
||||
"rarity": "SP"
|
||||
}
|
||||
],
|
||||
"details": "<h2><strong>开局因幡普攻主怪后锁二</strong></h2>"
|
||||
},
|
||||
{
|
||||
"shortDescription": "<h1>魂土15秒</h1><p><em>相同式神编辑不同属性</em></p>",
|
||||
"groupInfo": [
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/364.png",
|
||||
"name": "阿修罗",
|
||||
"rarity": "SSR",
|
||||
"properties": {
|
||||
"edit": true,
|
||||
"yuhun": {
|
||||
"yuhunSetEffect": [
|
||||
{
|
||||
"name": "狂骨",
|
||||
"shortName": "狂",
|
||||
"type": "attack",
|
||||
"avatar": "/assets/Yuhun/狂骨.png"
|
||||
},
|
||||
{
|
||||
"name": "荒骷髅",
|
||||
"shortName": "荒",
|
||||
"type": "PVE",
|
||||
"avatar": "/assets/Yuhun/荒骷髅.png"
|
||||
}
|
||||
],
|
||||
"target": "1",
|
||||
"property2": [
|
||||
"Attack"
|
||||
],
|
||||
"property4": [
|
||||
"Attack"
|
||||
],
|
||||
"property6": [
|
||||
"Crit",
|
||||
"CritDamage"
|
||||
]
|
||||
},
|
||||
"levelRequired": "40",
|
||||
"speed": "",
|
||||
"skillRequiredMode": "all",
|
||||
"skillRequired": [
|
||||
"5",
|
||||
"5",
|
||||
"5"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/364.png",
|
||||
"name": "阿修罗",
|
||||
"rarity": "SSR",
|
||||
"properties": {
|
||||
"edit": true,
|
||||
"yuhun": {
|
||||
"yuhunSetEffect": [
|
||||
{
|
||||
"name": "狂骨",
|
||||
"shortName": "狂",
|
||||
"type": "attack",
|
||||
"avatar": "/assets/Yuhun/狂骨.png"
|
||||
},
|
||||
{
|
||||
"name": "鬼灵歌伎",
|
||||
"shortName": "歌伎",
|
||||
"type": "PVE",
|
||||
"avatar": "/assets/Yuhun/鬼灵歌伎.png"
|
||||
}
|
||||
],
|
||||
"target": "0",
|
||||
"property2": [
|
||||
"Attack"
|
||||
],
|
||||
"property4": [
|
||||
"Attack"
|
||||
],
|
||||
"property6": [
|
||||
"Crit",
|
||||
"CritDamage"
|
||||
]
|
||||
},
|
||||
"levelRequired": "40",
|
||||
"speed": "",
|
||||
"skillRequiredMode": "all",
|
||||
"skillRequired": [
|
||||
"5",
|
||||
"5",
|
||||
"5"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/370.png",
|
||||
"name": "饭笥",
|
||||
"rarity": "SSR"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/ssr/369.png",
|
||||
"name": "食灵",
|
||||
"rarity": "SSR"
|
||||
},
|
||||
{
|
||||
"avatar": "/assets/Shikigami/r/205.png",
|
||||
"name": "座敷童子",
|
||||
"rarity": "R"
|
||||
}
|
||||
],
|
||||
"details": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Test",
|
||||
"name": "2",
|
||||
"visible": true,
|
||||
"type":"PVE",
|
||||
"groups": [
|
||||
{
|
||||
"shortDescription": "<h1>御魂·悲鸣</h1><p>这是一个演示项目,用于测试不同标签页的切换效果</p>",
|
||||
"groupInfo": [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"details": ""
|
||||
},
|
||||
{
|
||||
"shortDescription": "",
|
||||
"groupInfo": [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"details": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
activeFile: "1",
|
||||
}),
|
||||
getters: {
|
||||
visibleFiles: (state) => state.fileList.filter(file => file.visible),
|
||||
},
|
||||
actions: {
|
||||
addFile(file) {
|
||||
this.fileList.push({...file, visible: true});
|
||||
this.activeFile = file.name;
|
||||
},
|
||||
setActiveFile(fileId: number) {
|
||||
this.activeFile = fileId;
|
||||
},
|
||||
setVisible(fileId: number, visibility: boolean) {
|
||||
const file = this.fileList.find(file => file.name === fileId);
|
||||
if (file) {
|
||||
file.visible = visibility;
|
||||
}
|
||||
},
|
||||
closeTab(fileName: String) {
|
||||
const file = this.fileList.find(file => file.name === fileName);
|
||||
if (file) {
|
||||
file.visible = false;
|
||||
if (this.activeFile === fileName) {
|
||||
const nextVisibleFile = this.visibleFiles[0];
|
||||
this.activeFile = nextVisibleFile ? nextVisibleFile.name : -1;
|
||||
}
|
||||
}
|
||||
},
|
||||
async deleteFile(fileId: string) {
|
||||
try {
|
||||
if (this.fileList.length === 1) {
|
||||
showMessage('warning', '无法删除');
|
||||
return;
|
||||
}
|
||||
await ElMessageBox.confirm('确定要删除此文件吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
});
|
||||
|
||||
const index = this.fileList.findIndex(file => file.name === fileId);
|
||||
if (index > -1) {
|
||||
this.fileList.splice(index, 1);
|
||||
if (this.activeFile === fileId) {
|
||||
const nextVisibleFile = this.visibleFiles[0];
|
||||
this.activeFile = nextVisibleFile ? nextVisibleFile.name : "-1";
|
||||
}
|
||||
}
|
||||
showMessage('success', '删除成功!');
|
||||
} catch (error) {
|
||||
showMessage('info', '已取消删除');
|
||||
}
|
||||
},
|
||||
renameFile(fileId, newName) {
|
||||
const file = this.fileList.find(file => file.name === fileId);
|
||||
if (file) {
|
||||
file.label = newName;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
14
src/ts/useGlobalMessage.ts
Normal file
14
src/ts/useGlobalMessage.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
export function useGlobalMessage() {
|
||||
const showMessage = (type: 'success' | 'warning' | 'info' | 'error', message: string) => {
|
||||
ElMessage({
|
||||
type,
|
||||
message,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
showMessage,
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user