侧边栏填写style表单并实时预览

master
joefalmko 2 weeks ago
parent de8a257c8b
commit 11a27eec33

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

@ -11,8 +11,10 @@
"@ckeditor/ckeditor5-vue": "^7.2.0",
"ckeditor5": "^43.2.0",
"core-js": "^3.8.3",
"element-plus": "^2.8.7",
"file-saver": "^2.0.5",
"html-docx-js-typescript": "^0.1.5",
"mitt": "^3.0.1",
"vue": "^3.2.13"
},
"devDependencies": {
@ -21,8 +23,11 @@
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"babel-plugin-import": "^1.13.8",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"unplugin-auto-import": "^0.16.1",
"unplugin-vue-components": "^0.25.0"
}
},
"node_modules/@achrinza/node-ipc": {
@ -52,6 +57,15 @@
"node": ">=6.0.0"
}
},
"node_modules/@antfu/utils": {
"version": "0.7.10",
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
"integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.0",
"resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.26.0.tgz",
@ -2387,6 +2401,14 @@
"lodash-es": "4.17.21"
}
},
"node_modules/@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
"engines": {
"node": ">=10"
}
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmmirror.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@ -2396,6 +2418,14 @@
"node": ">=10.0.0"
}
},
"node_modules/@element-plus/icons-vue": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==",
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/@eslint/eslintrc": {
"version": "0.4.3",
"resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
@ -2452,6 +2482,28 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@floating-ui/core": {
"version": "1.6.8",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.6.8.tgz",
"integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
"dependencies": {
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.12",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.6.12.tgz",
"integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.8"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.8",
"resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.8.tgz",
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
},
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-9.3.0.tgz",
@ -2619,6 +2671,50 @@
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"dev": true
},
"node_modules/@popperjs/core": {
"name": "@sxzz/popperjs-es",
"version": "2.11.7",
"resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.3",
"resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
"integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@sideway/address": {
"version": "4.1.5",
"resolved": "https://registry.npmmirror.com/@sideway/address/-/address-4.1.5.tgz",
@ -2790,6 +2886,19 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/lodash": {
"version": "4.17.13",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.13.tgz",
"integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg=="
},
"node_modules/@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.5.tgz",
@ -2889,6 +2998,11 @@
"@types/node": "*"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"node_modules/@types/ws": {
"version": "8.5.12",
"resolved": "https://registry.npmmirror.com/@types/ws/-/ws-8.5.12.tgz",
@ -3562,6 +3676,89 @@
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
"dev": true
},
"node_modules/@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"dependencies": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.12.1",
"resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.12.1.tgz",
@ -3983,6 +4180,11 @@
"lodash": "^4.17.14"
}
},
"node_modules/async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -4071,6 +4273,15 @@
"object.assign": "^4.1.0"
}
},
"node_modules/babel-plugin-import": {
"version": "1.13.8",
"resolved": "https://registry.npmmirror.com/babel-plugin-import/-/babel-plugin-import-1.13.8.tgz",
"integrity": "sha512-36babpjra5m3gca44V6tSTomeBlPA7cHUynrE2WiQIm3rEGD9xy28MKsx5IdO45EbnpJY7Jrgd00C6Dwt/l/2Q==",
"dev": true,
"dependencies": {
"@babel/helper-module-imports": "^7.0.0"
}
},
"node_modules/babel-plugin-polyfill-corejs2": {
"version": "0.4.11",
"resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz",
@ -4792,6 +5003,12 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"dev": true
},
"node_modules/connect-history-api-fallback": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
@ -5263,6 +5480,11 @@
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz",
@ -5672,6 +5894,31 @@
"integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==",
"dev": true
},
"node_modules/element-plus": {
"version": "2.8.7",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.8.7.tgz",
"integrity": "sha512-oGQyFRufFOgjd872tZc+T4xQAYLlX4hj6d3ixeY13L4fFNUuc1N49JHAqJGPda0tdx3qCnjceZoh1kqqj2+tXQ==",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.3",
"escape-html": "^1.0.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -5799,8 +6046,7 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"dev": true
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
@ -7850,6 +8096,22 @@
"json5": "lib/cli.js"
}
},
"node_modules/local-pkg": {
"version": "0.5.0",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.0.tgz",
"integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
"dev": true,
"dependencies": {
"mlly": "^1.4.2",
"pkg-types": "^1.0.3"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
@ -7865,14 +8127,23 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
"peerDependencies": {
"@types/lodash-es": "*",
"lodash": "*",
"lodash-es": "*"
}
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -8148,6 +8419,11 @@
"node": ">= 4.0.0"
}
},
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"node_modules/merge-descriptors": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
@ -8363,6 +8639,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"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/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
@ -8375,6 +8656,18 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mlly": {
"version": "1.7.2",
"resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.2.tgz",
"integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==",
"dev": true,
"dependencies": {
"acorn": "^8.12.1",
"pathe": "^1.1.2",
"pkg-types": "^1.2.0",
"ufo": "^1.5.4"
}
},
"node_modules/module-alias": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz",
@ -8560,6 +8853,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
},
"node_modules/npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -8956,6 +9254,12 @@
"node": ">=8"
}
},
"node_modules/pathe": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@ -8985,6 +9289,17 @@
"node": ">=8"
}
},
"node_modules/pkg-types": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.2.1.tgz",
"integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==",
"dev": true,
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.2",
"pathe": "^1.1.2"
}
},
"node_modules/portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.32.tgz",
@ -10138,6 +10453,12 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/scule": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"dev": true
},
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz",
@ -10664,6 +10985,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-literal": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-2.1.0.tgz",
"integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==",
"dev": true,
"dependencies": {
"js-tokens": "^9.0.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/strip-literal/node_modules/js-tokens": {
"version": "9.0.0",
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.0.tgz",
"integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
"dev": true
},
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@ -11040,6 +11379,12 @@
"node": ">= 0.6"
}
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"dev": true
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.19.8.tgz",
@ -11086,6 +11431,48 @@
"node": ">=4"
}
},
"node_modules/unimport": {
"version": "3.13.1",
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-3.13.1.tgz",
"integrity": "sha512-nNrVzcs93yrZQOW77qnyOVHtb68LegvhYFwxFMfuuWScmwQmyVCG/NBuN8tYsaGzgQUVYv34E/af+Cc9u4og4A==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.1.2",
"acorn": "^8.12.1",
"escape-string-regexp": "^5.0.0",
"estree-walker": "^3.0.3",
"fast-glob": "^3.3.2",
"local-pkg": "^0.5.0",
"magic-string": "^0.30.11",
"mlly": "^1.7.1",
"pathe": "^1.1.2",
"pkg-types": "^1.2.0",
"scule": "^1.3.0",
"strip-literal": "^2.1.0",
"unplugin": "^1.14.1"
}
},
"node_modules/unimport/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/unimport/node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
@ -11104,6 +11491,175 @@
"node": ">= 0.8"
}
},
"node_modules/unplugin": {
"version": "1.15.0",
"resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-1.15.0.tgz",
"integrity": "sha512-jTPIs63W+DUEDW207ztbaoO7cQ4p5aVaB823LSlxpsFEU3Mykwxf3ZGC/wzxFJeZlASZYgVrWeo7LgOrqJZ8RA==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"webpack-sources": "^3"
},
"peerDependenciesMeta": {
"webpack-sources": {
"optional": true
}
}
},
"node_modules/unplugin-auto-import": {
"version": "0.16.1",
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.16.1.tgz",
"integrity": "sha512-H3Ky56cGEEHTssxUIFuGXTowGVlT/Bp3MBx1yyCzUHzAtdrO+2r9zpid32f2AkTpQxo2lch6yaTK61Im+rEyPQ==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.7.2",
"@rollup/pluginutils": "^5.0.2",
"local-pkg": "^0.4.3",
"magic-string": "^0.30.0",
"minimatch": "^9.0.1",
"unimport": "^3.0.7",
"unplugin": "^1.3.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@nuxt/kit": "^3.2.2",
"@vueuse/core": "*"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
},
"@vueuse/core": {
"optional": true
}
}
},
"node_modules/unplugin-auto-import/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/unplugin-auto-import/node_modules/local-pkg": {
"version": "0.4.3",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz",
"integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/unplugin-auto-import/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/unplugin-vue-components": {
"version": "0.25.0",
"resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.25.0.tgz",
"integrity": "sha512-HxrQ4GMSS1RwVww2av3a42cABo/v5AmTRN9iARv6e/xwkrfTyHhLh84kFwXxKkXK61vxDHxaryn694mQmkiVBg==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.7.3",
"@rollup/pluginutils": "^5.0.2",
"chokidar": "^3.5.3",
"debug": "^4.3.4",
"fast-glob": "^3.2.12",
"local-pkg": "^0.4.3",
"magic-string": "^0.30.0",
"minimatch": "^9.0.1",
"resolve": "^1.22.2",
"unplugin": "^1.3.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",
"vue": "2 || 3"
},
"peerDependenciesMeta": {
"@babel/parser": {
"optional": true
},
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/unplugin-vue-components/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/unplugin-vue-components/node_modules/local-pkg": {
"version": "0.4.3",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz",
"integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/unplugin-vue-components/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/unplugin/node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",

@ -11,6 +11,7 @@
"@ckeditor/ckeditor5-vue": "^7.2.0",
"ckeditor5": "^43.2.0",
"core-js": "^3.8.3",
"element-plus": "^2.8.7",
"file-saver": "^2.0.5",
"html-docx-js-typescript": "^0.1.5",
"vue": "^3.2.13"
@ -21,8 +22,11 @@
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"babel-plugin-import": "^1.13.8",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"unplugin-auto-import": "^0.16.1",
"unplugin-vue-components": "^0.25.0"
},
"eslintConfig": {
"root": true,
@ -33,9 +37,6 @@
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [

@ -0,0 +1,29 @@
### 角色
你是一个设计和 CSS 专家,能够根据用户需求生成精确的 CSS 样式。
### 任务
为以下元素生成 CSS 样式类:
标题:<hi>i为标题级别如 h1, h2 等)
文本块:<p>
块引用:<blockquote>
行文本:<span>
代码块:<pre>
所有样式都需在 .ck-content 中定义,格式为:
``` css
.ck-content element.class { ... }
```
### 示例
生成一个文本块样式,生成的样式如下所示。
``` css
.ck-content p.info-box {
--background-size: 30px;
--background-color: #e91e63;
padding: 1.2em 2em;
border: 1px solid var(--background-color);
background: linear-gradient(135deg, var(--background-color) 0%, var(--background-color) var(--background-size), transparent var(--background-size)), linear-gradient(135deg, transparent calc(100% - var(--background-size)), var(--background-color) calc(100% - var(--background-size)), var(--background-color));
border-radius: 10px;
margin: 1.5em 2em;
box-shadow: 5px 5px 0 #ffe6ef;
}
```
### 输出
仅输出你编写的 CSS 内容,不要对其进行解释和输出其他内容。

@ -9,6 +9,7 @@
.main-container {
/* --ckeditor5-preview-height: 700px; */
position:relative;
font-family: '宋体';
width: fit-content;
height: 100%;
@ -82,7 +83,67 @@
margin-left: 72px;
margin-right: 72px;
}
/*侧边栏样式*/
.sidebar {
position: fixed;
top: 0;
left: 0;
width: 350px;
height: 100%;
overflow-y: hidden;
transition: transform 0.3s ease;
transform: translateX(-100%);
background-color: #f9f9f9;
padding-left: 8px; /* 调整内边距,使文字右移 */
padding-right: 8px; /* 调整内边距,使文字右移 */
z-index: 9;
}
.sidebar.active {
transform: translateX(0);
}
.sidebar-menu {
display: flex;
justify-content: space-between;
}
.sidebar-menu .el-menu-item {
flex: 1;
text-align: center;
}
.sidebar-menu .el-menu-item span {
display: block;
padding: 10px;
background-color: #f5f5f5;
border-radius: 4px;
margin: 5px;
transition: background-color 0.3s;
}
.sidebar-menu .el-menu-item span:hover {
background-color: #e0e0e0;
}
.chat-box {
max-height: 350px;
overflow-y: auto;
}
.preview {
margin-top: 20px; /* 调整预览区与表单之间的距离 */
border: 1px solid #ccc; /* 添加边框 */
padding: 10px; /* 添加内边距 */
border-radius: 4px; /* 添加圆角 */
}
.form-item {
margin-bottom: 1px; /* 减小表单项之间的距离 */
}
/*侧边栏出现时其他右移*/
.main-container.sidebar-open .editor-container__menu-bar,
.main-container.sidebar-open .editor-container__toolbar,
.main-container.sidebar-open .editor-container__editor-wrapper {
transition: margin-left 0.3s ease;
margin-left: 350px;
}
/*用户定义的style插件样式*/
.ck-content h3.category {
font-family: 'Oswald';
font-size: 20px;

@ -1,22 +1,225 @@
<template>
<div>
<div class="main-container">
<div class="editor-container editor-container_document-editor editor-container_include-style"
ref="editorContainerElement">
<div class="editor-container__menu-bar" ref="editorMenuBarElement"></div>
<div class="editor-container__toolbar" ref="editorToolbarElement"></div>
<div class="editor-container__editor-wrapper">
<div class="editor-container__editor">
<div ref="editorElement">
<ckeditor v-if="isLayoutReady" v-model="config.initialData" :editor="editor"
:config="config" @ready="onReady" />
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<div :class="['main-container', { 'sidebar-open': isSidebarOpen }]">
<div class="editor-container editor-container_document-editor editor-container_include-style"
ref="editorContainerElement">
<div class="editor-container__menu-bar" ref="editorMenuBarElement"></div>
<div class="editor-container__toolbar" ref="editorToolbarElement"></div>
<div class="editor-container__editor-wrapper">
<div class="editor-container__editor">
<div ref="editorElement">
<ckeditor v-if="isLayoutReady" v-model="config.initialData" :editor="editor"
:config="config" @ready="onReady" />
</div>
</div>
</div>
<el-button type="primary" @click="toggleSidebar()" style="display:none" id="toggleSidebarButton">打开/关闭侧边栏</el-button>
<div class="sidebar" :class="{ 'active': isSidebarOpen }">
<!-- 侧边栏内容 -->
<el-menu default-active="1" class="el-menu-vertical-demo sidebar-menu">
<el-menu-item index="1" @click="showForm('manual')">
<span>手动输入</span>
</el-menu-item>
<el-menu-item index="2" @click="showForm('ai')">
<span>AI 输入</span>
</el-menu-item>
</el-menu>
<div v-if="currentForm === 'manual'" class="p-3">
<!-- 手动输入表单 -->
<el-form @submit.prevent="submitForm">
<el-col :span="30">
<el-form-item label="字体颜色:">
<el-col :span="10">
<el-select v-model="formData.color" @change="updatePreview">
<el-option label="黑色" value="black" style="background-color: black;">黑色</el-option>
<el-option label="红色" value="red" style="background-color: red;">红色</el-option>
<el-option label="蓝色" value="blue" style="background-color: blue;">蓝色</el-option>
<el-option label="绿色" value="green" style="background-color: green;">绿色</el-option>
<el-option label="黄色" value="yellow" style="background-color: yellow;">黄色</el-option>
<el-option label="紫色" value="purple" style="background-color: purple;">紫色</el-option>
<el-option label="橙色" value="orange" style="background-color: orange">橙色</el-option>
</el-select>
</el-col>
<el-col :span="8">
<el-color-picker v-model="formData.color" @change="updatePreview"></el-color-picker>
</el-col>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="字体大小:">
<el-row :gutter="10">
<el-col :span="12">
<el-select v-model="formData.fontSize" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="12px">12px</el-option>
<el-option value="14px">14px</el-option>
<el-option value="16px">16px</el-option>
<el-option value="18px">18px</el-option>
</el-select>
</el-col>
<el-col :span="12">
<el-input v-model="formData.fontSize" placeholder="例如: 16px" @input="updatePreview"></el-input>
</el-col>
</el-row>
</el-form-item>
</el-col>
<!-- 字体选择 -->
<el-row :gutter="8">
<el-col :span="12">
<el-form-item label="字体:">
<el-select v-model="formData.fontFamily" @change="updatePreview">
<!--英文字体-->
<el-option value="">请选择</el-option>
<el-option value="Arial">Arial</el-option>
<el-option value="Courier New">Courier New</el-option>
<el-option value="Georgia">Georgia</el-option>
<el-option value="Helvetica">Helvetica</el-option>
<el-option value="Times New Roman">Times New Roman</el-option>
<el-option value="serif">serif</el-option>
<el-option value="sans-serif">sans-serif</el-option>
<el-option value="monospace">monospace</el-option>
<el-option value="cursive">cursive</el-option>
<el-option value="fantasy">fantasy</el-option>
<!--中文字体字体-->
<el-option value="SimSun">宋体</el-option>
<el-option value="SimHei">黑体</el-option>
<el-option value="Microsoft YaHei">微软雅黑</el-option>
<el-option value="FangSong">仿宋</el-option>
<el-option value="KaiTi">楷体</el-option>
<el-option value="LiSu">隶书</el-option>
<el-option value="YouYuan">幼圆</el-option>
<el-option value="STSong">华文宋体</el-option>
<el-option value="STHeiti">华文黑体</el-option>
<el-option value="STKaiti">华文楷体</el-option>
<el-option value="STFangsong">华文仿宋</el-option>
<el-option value="STXihei">华文细黑</el-option>
<el-option value="STCaiyun">华文彩云</el-option>
<el-option value="STHupo">华文琥珀</el-option>
<el-option value="STXinwei">华文新魏</el-option>
<el-option value="STXingkai">华文行楷</el-option>
<el-option value="FZShuTi">方正舒体</el-option>
<el-option value="FZYaoti">方正姚体</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字体样式:">
<el-select v-model="formData.fontStyle" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="normal">正常</el-option>
<el-option value="italic">斜体</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字体粗细:">
<el-select v-model="formData.fontWeight" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="normal">正常</el-option>
<el-option value="bold">加粗</el-option>
<el-option value="bolder">更粗</el-option>
<el-option value="lighter">更细</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="文本转换:">
<el-select v-model="formData.textTransform" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="none"></el-option>
<el-option value="uppercase">大写</el-option>
<el-option value="lowercase">小写</el-option>
<el-option value="capitalize">首字母大写</el-option>
<el-option value="full-width">全角</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="文本装饰:">
<el-select v-model="formData.textDecoration" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="none"></el-option>
<el-option value="underline">下划线</el-option>
<el-option value="overline">上划线</el-option>
<el-option value="line-through">删除线</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字体阴影:">
<el-select v-model="formData.textShadow" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="2px 2px 4px rgba(0,0,0,0.5)">阴影1</el-option>
<el-option value="4px 4px 8px rgba(0,0,0,0.5)">阴影2</el-option>
<el-option value="6px 6px 12px rgba(0,0,0,0.5)">阴影3</el-option>
<el-option value="-1px -1px 1px #aaa">阴影4</el-option>
<el-option value="0px 4px 1px rgba(0, 0, 0, 0.5)">阴影5</el-option>
<el-option value="4px 4px 5px rgba(0, 0, 0, 0.7)">阴影6</el-option>
<el-option value="0px 0px 7px rgba(0, 0, 0, 0.4)">阴影7</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="文本对齐:">
<el-select v-model="formData.textAlign" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="left">左对齐</el-option>
<el-option value="center">居中</el-option>
<el-option value="right">右对齐</el-option>
<el-option value="justify">两端对齐</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="行高:">
<el-select v-model="formData.lineHeight" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="1.0">1.0</el-option>
<el-option value="1.5">1.5</el-option>
<el-option value="2.0">2.0</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字母间距:">
<el-select v-model="formData.letterSpacing" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="0">0</el-option>
<el-option value="1px">1px</el-option>
<el-option value="2px">2px</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单词间距:">
<el-select v-model="formData.wordSpacing" @change="updatePreview">
<el-option value="">请选择</el-option>
<el-option value="0">0</el-option>
<el-option value="1px">1px</el-option>
<el-option value="2px">2px</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item><el-button type="success" native-type="submit" class="w-100">提交</el-button></el-form-item>
</el-form>
<div class="preview mt-3 p-3 border rounded" :style="previewStyle">
Aa Bb Cc 上下 左右 12345 Aa Bb Cc 上下 左右 12345 Aa Bb Cc 上下 左右 12345
</div>
</div>
<div v-if="currentForm === 'ai'" class="p-3">
<!-- AI对话框 -->
<div class="chat-box border rounded p-3">
<p v-for="message in messages" :key="message.id" class="mb-1">{{ message.text }}</p>
<el-input v-model="aiInput" @keyup.enter="sendMessageToAI" placeholder="请输入消息" class="w-100"></el-input>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
// DecoupledEditor,
@ -90,212 +293,13 @@ import {
TodoList,
Underline,
Undo,
//
Plugin,
ButtonView,
// ToolbarView,
// DropdownMenuRootListView,
createDropdown,
// SplitButtonView,
Collection,
addListToDropdown,
// Position,
// Model,
// addToolbarToDropdown
} from 'ckeditor5';
// import translations from 'ckeditor5/translations/zh-cn.js';
import translations from 'ckeditor5/translations/zh-cn.js';
import 'ckeditor5/ckeditor5.css';
import {ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu,ElMenuItem,ElColorPicker} from 'element-plus';
import {getUserConfigFromBackend,saveData,getPageContent,getAndApplyUserStyles} from './components/utils';
import {Export2PDF,Export2Word,ToggleSideBar,Translation} from './components/plugins'
import { asBlob } from 'html-docx-js-typescript'
import { saveAs } from 'file-saver';
// import Plugin from "@ckeditor/ckeditor5-core/src/plugin";
// import Model from "@ckeditor/ckeditor5-ui/src/model";
// import Collection from "@ckeditor/ckeditor5-utils/src/collection";
// import {addListToDropdown,createDropdown} from "@ckeditor/ckeditor5-ui/src/dropdown/utils";
// import SplitButtonView from "@ckeditor/ckeditor5-ui/src/dropdown/button/splitbuttonview";
//
function getStyle() {
let str = '<head><meta charset="utf-8"></meta>';
const styles = document.querySelectorAll('style');
for (let i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>.results{width:100%!important;} .result .title{width:100%;}</style>";
str += "<style>table{border-collapse: collapse;table-layout: fixed}</style>"
// str += "<style>table thead tr{ background-color: #f3f4f9;}</style>"
str += "<style>table td,th{ font-size: 14px;padding: 1px 1px;border-width: 1px;border-style: solid;border-color: #d0d0d0;word-break: keep-all;white-space: nowrap;}</style>"
return str;
}
// <html>
function getPageContent(){
const pageContent = document.querySelector("#app > div > div > div > div.editor-container__editor-wrapper > div > div > div.ck.ck-reset.ck-editor.ck-rounded-corners > div.ck.ck-editor__main")
return pageContent.innerHTML;
}
// docx
class Export2Word extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add('ExportToWord', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set({
label: '导出为docx',
// withText: true
tooltip: true,
// svg
icon: '<svg t="1730216969869" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2612" width="200" height="200"><path d="M576 832H224c-17.6 0-32-14.4-32-32V192h608c17.6 0 32 14.4 32 32v288c0 17.7 14.3 32 32 32s32-14.3 32-32V224c0-52.9-43.1-96-96-96H160c-17.7 0-32 14.3-32 32v640c0 52.9 43.1 96 96 96h352c17.7 0 32-14.3 32-32s-14.3-32-32-32z" p-id="2613"></path><path d="M951.7 757.5c0.2-0.2 0.4-0.5 0.6-0.7 0.1-0.2 0.3-0.3 0.4-0.5 0.2-0.3 0.4-0.6 0.7-0.8 0.1-0.1 0.2-0.3 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.2 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.3 0.2-0.4 0.2-0.3 0.4-0.6 0.5-0.9 0.1-0.1 0.2-0.3 0.3-0.4 0.2-0.3 0.3-0.6 0.4-0.9 0.1-0.2 0.2-0.4 0.3-0.5 0.1-0.3 0.2-0.5 0.4-0.8 0.1-0.2 0.2-0.4 0.3-0.7 0.1-0.2 0.2-0.5 0.3-0.7 0.1-0.3 0.2-0.5 0.3-0.8 0.1-0.2 0.1-0.4 0.2-0.6l0.3-0.9c0.1-0.2 0.1-0.4 0.2-0.6 0.1-0.3 0.2-0.6 0.3-1 0-0.2 0.1-0.3 0.1-0.5 0.1-0.3 0.2-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.5 0.1-0.3 0.1-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.6 0-0.3 0.1-0.6 0.1-0.9 0-0.3 0-0.5 0.1-0.8 0-0.2 0-0.5 0.1-0.7 0.1-1.1 0.1-2.1 0-3.2 0-0.3 0-0.5-0.1-0.7 0-0.3 0-0.5-0.1-0.8 0-0.3-0.1-0.6-0.1-0.9 0-0.2 0-0.4-0.1-0.6 0-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.4-0.1-0.5-0.1-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.3-0.1-0.5-0.1-0.3-0.2-0.6-0.3-1-0.1-0.2-0.1-0.4-0.2-0.6l-0.3-0.9c-0.1-0.2-0.1-0.4-0.2-0.6-0.1-0.3-0.2-0.5-0.3-0.8-0.1-0.2-0.2-0.5-0.3-0.7-0.1-0.2-0.2-0.4-0.3-0.7-0.1-0.3-0.2-0.5-0.4-0.8-0.1-0.2-0.2-0.4-0.3-0.5-0.1-0.3-0.3-0.6-0.4-0.9-0.1-0.2-0.2-0.3-0.3-0.4-0.2-0.3-0.3-0.6-0.5-0.9-0.1-0.1-0.2-0.3-0.2-0.4l-0.6-0.9c-0.1-0.1-0.2-0.2-0.3-0.4l-0.6-0.9c-0.1-0.1-0.2-0.3-0.3-0.4-0.2-0.3-0.4-0.6-0.7-0.8-0.1-0.2-0.3-0.3-0.4-0.5-0.2-0.2-0.4-0.5-0.6-0.7-0.2-0.2-0.4-0.5-0.7-0.7l-0.4-0.4-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l73.4 73.4H592c-17.7 0-32 14.3-32 32s14.3 32 32 32h258.7l-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3 6.2 6.2 14.4 9.4 22.6 9.4s16.4-3.1 22.6-9.4l128-128 0.4-0.4c0.4-0.6 0.6-0.9 0.8-1.1z" p-id="2614"></path><path d="M709.3 320.4c-17.4-2.9-33.9 8.9-36.8 26.3l-42.8 256.9-87.3-261.8c-4.4-13-16.6-21.8-30.4-21.8-13.8 0-26 8.8-30.4 21.9l-87.3 261.8-42.8-256.9c-2.9-17.4-19.4-29.2-36.8-26.3-17.4 2.9-29.2 19.4-26.3 36.8l64 384c2.4 14.5 14.4 25.5 29.1 26.6 14.7 1.1 28.2-7.8 32.9-21.8L512 453.2l66.4 199.1c3.9 11.8 15 19.8 27.4 19.8h52.9c14.1 0 26.2-10.2 28.5-24.1l48.4-290.6c2.9-17.6-8.9-34.1-26.3-37z" p-id="2615"></path></svg>'
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
const pageContent = getPageContent();
const style = getStyle();
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent + '</body></html>'
// console.log(page);
asBlob(page).then(data => {
saveAs(data, 'file.docx') // save as docx file
}); // asBlob() return Promise<Blob|Buffer>
});
return button;
});
//
// editor.ui.extendMenuBar({
// menu: {
// menuId: 'export',
// label: '',
// groups: [
// {
// groupId: 'export',
// items: [
// 'ExportToWord'
// ]
// }
// ]
// },
// position: 'after:help'
// }
// );
}
}
// PDF
class Export2PDF extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add('ExportToPDF', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set({
label: '导出为PDF',
// withText: true
tooltip: true,
// svg
icon: '<svg t="1730309942693" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2589" width="200" height="200"><path d="M576 832H224c-17.6 0-32-14.4-32-32V192h608c17.6 0 32 14.4 32 32v288c0 17.7 14.3 32 32 32s32-14.3 32-32V224c0-52.9-43.1-96-96-96H160c-17.7 0-32 14.3-32 32v640c0 52.9 43.1 96 96 96h352c17.7 0 32-14.3 32-32s-14.3-32-32-32z" p-id="2590"></path><path d="M960 734.4c0-0.3 0-0.5-0.1-0.7 0-0.3 0-0.5-0.1-0.8 0-0.3-0.1-0.6-0.1-0.9 0-0.2 0-0.4-0.1-0.6 0-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.4-0.1-0.5-0.1-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.3-0.1-0.5-0.1-0.3-0.2-0.6-0.3-1-0.1-0.2-0.1-0.4-0.2-0.6l-0.3-0.9c-0.1-0.2-0.1-0.4-0.2-0.6-0.1-0.3-0.2-0.5-0.3-0.8-0.1-0.2-0.2-0.5-0.3-0.7-0.1-0.2-0.2-0.4-0.3-0.7-0.1-0.3-0.2-0.5-0.4-0.8-0.1-0.2-0.2-0.4-0.3-0.5-0.1-0.3-0.3-0.6-0.4-0.9-0.1-0.2-0.2-0.3-0.3-0.4-0.2-0.3-0.3-0.6-0.5-0.9-0.1-0.1-0.2-0.3-0.2-0.4l-0.6-0.9c-0.1-0.1-0.2-0.2-0.3-0.4l-0.6-0.9c-0.1-0.1-0.2-0.3-0.3-0.4-0.2-0.3-0.4-0.6-0.7-0.8-0.1-0.2-0.3-0.3-0.4-0.5-0.2-0.2-0.4-0.5-0.6-0.7-0.2-0.2-0.4-0.5-0.7-0.7l-0.4-0.4-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l73.4 73.4H592c-17.7 0-32 14.3-32 32s14.3 32 32 32h258.7l-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3 6.2 6.2 14.4 9.4 22.6 9.4s16.4-3.1 22.6-9.4l128-128 0.4-0.4 0.7-0.7c0.2-0.2 0.4-0.5 0.6-0.7 0.1-0.2 0.3-0.3 0.4-0.5 0.2-0.3 0.4-0.6 0.7-0.8 0.1-0.1 0.2-0.3 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.2 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.3 0.2-0.4 0.2-0.3 0.4-0.6 0.5-0.9 0.1-0.1 0.2-0.3 0.3-0.4 0.2-0.3 0.3-0.6 0.4-0.9 0.1-0.2 0.2-0.4 0.3-0.5 0.1-0.3 0.2-0.5 0.4-0.8 0.1-0.2 0.2-0.4 0.3-0.7 0.1-0.2 0.2-0.5 0.3-0.7 0.1-0.3 0.2-0.5 0.3-0.8 0.1-0.2 0.1-0.4 0.2-0.6l0.3-0.9c0.1-0.2 0.1-0.4 0.2-0.6 0.1-0.3 0.2-0.6 0.3-1 0-0.2 0.1-0.3 0.1-0.5 0.1-0.3 0.2-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.5 0.1-0.3 0.1-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.6 0-0.3 0.1-0.6 0.1-0.9 0-0.3 0-0.5 0.1-0.8 0-0.2 0-0.5 0.1-0.7-0.1-1.5-0.1-2.5-0.1-3.6zM352 320c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32s32-14.3 32-32V576h192c70.6 0 128-57.4 128-128s-57.4-128-128-128H352z m288 128c0 35.3-28.7 64-64 64H384V384h192c35.3 0 64 28.7 64 64z" p-id="2591"></path></svg>'
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
const pageContent = getPageContent();
const style = getStyle();
// element ck-focused ck-weight_selected
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent.replaceAll('ck-focused', 'ck-blurred').replaceAll('ck-weight_selected', '') + '</body></html>'
const newWindow = window.open('', 'PrintDocument', 'height=600,width=700,top=50,left=50');
newWindow.document.write(page);
newWindow.document.close();
newWindow.print();
newWindow.onafterprint = function () {
newWindow.close();
}
});
return button;
});
}
}
//
class Translation extends Plugin {
init() {
// console.log('Translation initialized!');
this.editor.ui.componentFactory.add('translate', (locale) => {
const dropdownView = createDropdown(locale);
dropdownView.buttonView.set({
label: '智能助手',
withText: true,
});
const items = new Collection();
items.add({
type: 'button',
model: {
id: 'summary',
withText: true,
label: '摘要',
}
});
items.add({
type: 'button',
model: {
id: 'decoration',
withText: true,
label: '润色'
}
});
items.add({
type: 'button',
model: {
id: 'extension',
withText: true,
label: '续写'
}
});
items.add({
type: 'button',
model: {
id: 'correction',
withText: true,
label: '修改'
}
});
items.add({
type: 'button',
model: {
id: 'translation',
withText: true,
label: '翻译'
}
});
addListToDropdown(dropdownView, items);
dropdownView.on('execute', (eventInfo) => {
const { id, label } = eventInfo.source;
//
const selectionText = window.getSelection().toString();
if (id === 'summary') {
// this.editor.execute('ExportToWord');
console.log('Object (en):', label, selectionText);
}
});
return dropdownView;
});
}
}
export default {
name: 'app',
data() {
@ -303,11 +307,35 @@ export default {
isLayoutReady: false,
config: null, // CKEditor needs the DOM tree before calculating the configuration.
// editor: DecoupledEditor
editor: ClassicEditor
editor: ClassicEditor,
isSidebarOpen:false,//
currentForm:'', //
formData: {
fontFamily: '',
color: '',
fontSize: '',
fontStyle: '',
fontWeight: '',
textTransform: '',
textDecoration: '',
textShadow: '',
textAlign: '',
lineHeight: '',
letterSpacing: '',
wordSpacing: ''
},
previewStyle:{},
aiInput: '', // AI
messages: [], //
};
},
mounted() {
//
const userConfig = getUserConfigFromBackend();
//
getAndApplyUserStyles();
this.config = {
toolbar: {
items: [
@ -338,7 +366,7 @@ export default {
'numberedList',
'outdent',
'indent',
'|', 'ExportToWord', 'ExportToPDF', 'translate'
'|', 'ExportToWord', 'ExportToPDF', 'translate','SideBar'
],
shouldNotGroupWhenFull: true
},
@ -412,7 +440,7 @@ export default {
TodoList,
Underline,
Undo,
Export2Word, Translation, Export2PDF
Export2Word, Translation, Export2PDF,ToggleSideBar
],
balloonToolbar: ['bold', 'italic', '|', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'],
//
@ -494,11 +522,8 @@ export default {
'resizeImage'
]
},
// /
//
// TODO
initialData:
'<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li>⭐️ <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑‍💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n',
'',
language: 'zh-cn',
link: {
addTargetToExternalLinks: true,
@ -549,8 +574,7 @@ export default {
return saveData( getPageContent() );
}
},
// translations: [translations]
translations: [translations]
};
this.isLayoutReady = true;
@ -562,121 +586,55 @@ export default {
this.$refs.editorToolbarElement.appendChild(editor.ui.view.toolbar.element);
this.$refs.editorMenuBarElement.appendChild(editor.ui.view.menuBarView.element);
}
//
const pageContent = '<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li>⭐️ <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑‍💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n';
// pageContent
// TODO
editor.setData( pageContent );
},
// sidebar
// /
toggleSidebar(){
this.isSidebarOpen = !this.isSidebarOpen;
},
//
showForm(formType){
this.currentForm = formType;
},
//
submitForm() {
const selectedStyles = {};
for (const key in this.formData) {
if (this.formData[key]) {
selectedStyles[key] = this.formData[key];
}
}
console.log(selectedStyles); // selectedStyles
alert(JSON.stringify(selectedStyles, null, 2));
},
//
updatePreview() {
this.previewStyle = {};
for (const key in this.formData) {
if (this.formData[key]) {
this.previewStyle[key] = this.formData[key];
}
}
},
// API
sendMessageToAI() {
// APIAI
this.messages.push({ text: this.aiInput });
this.aiInput = ''; //
// AI
setTimeout(() => {
this.messages.push({ text: '这是来自AI的回复' });
}, 1000);
},
},
components: {
//
ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem,ElMenu,ElMenuItem,ElColorPicker
}
};
//
function getUserConfigFromBackend(){
// TODO
const options={}
//
// TODO
const {
fontFamilyOptions = [
'default',
'宋体',
'新宋体',
'仿宋',
'楷体',
'微软雅黑',
'黑体',
'华文仿宋',
'华文楷体',
'华文隶书',
'华文宋体',
'华文细黑',
'华文新魏',
'华文行楷',
'华文中宋',
'隶书',
'苹方 常规',
'幼圆',
'Times New Roman'
],
//
fontSizeOptions = [10.5, 12, 14,15, 'default', 18,22],
styleDefinitions = [
{
name: 'Article category',
element: 'h3',
classes: ['category']
},
{
name: 'Title',
element: 'h2',
classes: ['document-title']
},
{
name: 'Subtitle',
element: 'h3',
classes: ['document-subtitle']
},
{
name: 'Info box',
element: 'p',
classes: ['info-box']
},
{
name: 'Side quote',
element: 'blockquote',
classes: ['side-quote']
},
{
name: 'Marker',
element: 'span',
classes: ['marker']
},
{
name: 'Spoiler',
element: 'span',
classes: ['spoiler']
},
{
name: 'Code (dark)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-dark']
},
{
name: 'Code (bright)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-bright']
},
{
name: 'GradientBorder',
element: 'p',
classes: ['gradientborder']
}
]
} = options;
// options使
return {
fontFamily: {
options: fontFamilyOptions
},
fontSize: {
options: fontSizeOptions
},
style: {
definitions: styleDefinitions
}
};
}
// TODO saveData
function saveData( data ) {
// return new Promise( resolve => {
// setTimeout( () => {
// console.log( 'Saved', data );
// resolve();
// }, HTTP_SERVER_LAG );
// } );
console.log(data);
}
// TODO
// function saveByHand(){
// this.editor.plugins.get('Autosave').save().then(() => {
// console.log('Data saved successfully');
// });
// }
</script>

@ -0,0 +1,212 @@
import {
Plugin,
ButtonView,
createDropdown,
Collection,
addListToDropdown,
} from 'ckeditor5';
import { asBlob } from 'html-docx-js-typescript'
import { saveAs } from 'file-saver';
import {
getStyle,
getPageContent
} from './utils';
// 导出为docx插件
class Export2Word extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add('ExportToWord', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set({
label: '导出为docx',
// withText: true
tooltip: true,
// 图标 直接插入svg文件
icon: '<svg t="1730216969869" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2612" width="200" height="200"><path d="M576 832H224c-17.6 0-32-14.4-32-32V192h608c17.6 0 32 14.4 32 32v288c0 17.7 14.3 32 32 32s32-14.3 32-32V224c0-52.9-43.1-96-96-96H160c-17.7 0-32 14.3-32 32v640c0 52.9 43.1 96 96 96h352c17.7 0 32-14.3 32-32s-14.3-32-32-32z" p-id="2613"></path><path d="M951.7 757.5c0.2-0.2 0.4-0.5 0.6-0.7 0.1-0.2 0.3-0.3 0.4-0.5 0.2-0.3 0.4-0.6 0.7-0.8 0.1-0.1 0.2-0.3 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.2 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.3 0.2-0.4 0.2-0.3 0.4-0.6 0.5-0.9 0.1-0.1 0.2-0.3 0.3-0.4 0.2-0.3 0.3-0.6 0.4-0.9 0.1-0.2 0.2-0.4 0.3-0.5 0.1-0.3 0.2-0.5 0.4-0.8 0.1-0.2 0.2-0.4 0.3-0.7 0.1-0.2 0.2-0.5 0.3-0.7 0.1-0.3 0.2-0.5 0.3-0.8 0.1-0.2 0.1-0.4 0.2-0.6l0.3-0.9c0.1-0.2 0.1-0.4 0.2-0.6 0.1-0.3 0.2-0.6 0.3-1 0-0.2 0.1-0.3 0.1-0.5 0.1-0.3 0.2-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.5 0.1-0.3 0.1-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.6 0-0.3 0.1-0.6 0.1-0.9 0-0.3 0-0.5 0.1-0.8 0-0.2 0-0.5 0.1-0.7 0.1-1.1 0.1-2.1 0-3.2 0-0.3 0-0.5-0.1-0.7 0-0.3 0-0.5-0.1-0.8 0-0.3-0.1-0.6-0.1-0.9 0-0.2 0-0.4-0.1-0.6 0-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.4-0.1-0.5-0.1-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.3-0.1-0.5-0.1-0.3-0.2-0.6-0.3-1-0.1-0.2-0.1-0.4-0.2-0.6l-0.3-0.9c-0.1-0.2-0.1-0.4-0.2-0.6-0.1-0.3-0.2-0.5-0.3-0.8-0.1-0.2-0.2-0.5-0.3-0.7-0.1-0.2-0.2-0.4-0.3-0.7-0.1-0.3-0.2-0.5-0.4-0.8-0.1-0.2-0.2-0.4-0.3-0.5-0.1-0.3-0.3-0.6-0.4-0.9-0.1-0.2-0.2-0.3-0.3-0.4-0.2-0.3-0.3-0.6-0.5-0.9-0.1-0.1-0.2-0.3-0.2-0.4l-0.6-0.9c-0.1-0.1-0.2-0.2-0.3-0.4l-0.6-0.9c-0.1-0.1-0.2-0.3-0.3-0.4-0.2-0.3-0.4-0.6-0.7-0.8-0.1-0.2-0.3-0.3-0.4-0.5-0.2-0.2-0.4-0.5-0.6-0.7-0.2-0.2-0.4-0.5-0.7-0.7l-0.4-0.4-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l73.4 73.4H592c-17.7 0-32 14.3-32 32s14.3 32 32 32h258.7l-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3 6.2 6.2 14.4 9.4 22.6 9.4s16.4-3.1 22.6-9.4l128-128 0.4-0.4c0.4-0.6 0.6-0.9 0.8-1.1z" p-id="2614"></path><path d="M709.3 320.4c-17.4-2.9-33.9 8.9-36.8 26.3l-42.8 256.9-87.3-261.8c-4.4-13-16.6-21.8-30.4-21.8-13.8 0-26 8.8-30.4 21.9l-87.3 261.8-42.8-256.9c-2.9-17.4-19.4-29.2-36.8-26.3-17.4 2.9-29.2 19.4-26.3 36.8l64 384c2.4 14.5 14.4 25.5 29.1 26.6 14.7 1.1 28.2-7.8 32.9-21.8L512 453.2l66.4 199.1c3.9 11.8 15 19.8 27.4 19.8h52.9c14.1 0 26.2-10.2 28.5-24.1l48.4-290.6c2.9-17.6-8.9-34.1-26.3-37z" p-id="2615"></path></svg>'
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
const pageContent = getPageContent();
const style = getStyle();
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent + '</body></html>'
// console.log(page);
asBlob(page).then(data => {
saveAs(data, 'file.docx') // save as docx file
}); // asBlob() return Promise<Blob|Buffer>
});
return button;
});
// 增加菜单栏? 不显示按钮
// editor.ui.extendMenuBar({
// menu: {
// menuId: 'export',
// label: '导出',
// groups: [
// {
// groupId: 'export',
// items: [
// 'ExportToWord'
// ]
// }
// ]
// },
// position: 'after:help'
// }
// );
}
}
// 导出为PDF插件
class Export2PDF extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add('ExportToPDF', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set({
label: '导出为PDF',
// withText: true
tooltip: true,
// 图标 直接插入svg文件
icon: '<svg t="1730309942693" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2589" width="200" height="200"><path d="M576 832H224c-17.6 0-32-14.4-32-32V192h608c17.6 0 32 14.4 32 32v288c0 17.7 14.3 32 32 32s32-14.3 32-32V224c0-52.9-43.1-96-96-96H160c-17.7 0-32 14.3-32 32v640c0 52.9 43.1 96 96 96h352c17.7 0 32-14.3 32-32s-14.3-32-32-32z" p-id="2590"></path><path d="M960 734.4c0-0.3 0-0.5-0.1-0.7 0-0.3 0-0.5-0.1-0.8 0-0.3-0.1-0.6-0.1-0.9 0-0.2 0-0.4-0.1-0.6 0-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.4-0.1-0.5-0.1-0.3-0.1-0.7-0.2-1 0-0.2-0.1-0.3-0.1-0.5-0.1-0.3-0.2-0.6-0.3-1-0.1-0.2-0.1-0.4-0.2-0.6l-0.3-0.9c-0.1-0.2-0.1-0.4-0.2-0.6-0.1-0.3-0.2-0.5-0.3-0.8-0.1-0.2-0.2-0.5-0.3-0.7-0.1-0.2-0.2-0.4-0.3-0.7-0.1-0.3-0.2-0.5-0.4-0.8-0.1-0.2-0.2-0.4-0.3-0.5-0.1-0.3-0.3-0.6-0.4-0.9-0.1-0.2-0.2-0.3-0.3-0.4-0.2-0.3-0.3-0.6-0.5-0.9-0.1-0.1-0.2-0.3-0.2-0.4l-0.6-0.9c-0.1-0.1-0.2-0.2-0.3-0.4l-0.6-0.9c-0.1-0.1-0.2-0.3-0.3-0.4-0.2-0.3-0.4-0.6-0.7-0.8-0.1-0.2-0.3-0.3-0.4-0.5-0.2-0.2-0.4-0.5-0.6-0.7-0.2-0.2-0.4-0.5-0.7-0.7l-0.4-0.4-128-128c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l73.4 73.4H592c-17.7 0-32 14.3-32 32s14.3 32 32 32h258.7l-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3 6.2 6.2 14.4 9.4 22.6 9.4s16.4-3.1 22.6-9.4l128-128 0.4-0.4 0.7-0.7c0.2-0.2 0.4-0.5 0.6-0.7 0.1-0.2 0.3-0.3 0.4-0.5 0.2-0.3 0.4-0.6 0.7-0.8 0.1-0.1 0.2-0.3 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.2 0.3-0.4l0.6-0.9c0.1-0.1 0.2-0.3 0.2-0.4 0.2-0.3 0.4-0.6 0.5-0.9 0.1-0.1 0.2-0.3 0.3-0.4 0.2-0.3 0.3-0.6 0.4-0.9 0.1-0.2 0.2-0.4 0.3-0.5 0.1-0.3 0.2-0.5 0.4-0.8 0.1-0.2 0.2-0.4 0.3-0.7 0.1-0.2 0.2-0.5 0.3-0.7 0.1-0.3 0.2-0.5 0.3-0.8 0.1-0.2 0.1-0.4 0.2-0.6l0.3-0.9c0.1-0.2 0.1-0.4 0.2-0.6 0.1-0.3 0.2-0.6 0.3-1 0-0.2 0.1-0.3 0.1-0.5 0.1-0.3 0.2-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.5 0.1-0.3 0.1-0.7 0.2-1 0-0.2 0.1-0.4 0.1-0.6 0-0.3 0.1-0.6 0.1-0.9 0-0.3 0-0.5 0.1-0.8 0-0.2 0-0.5 0.1-0.7-0.1-1.5-0.1-2.5-0.1-3.6zM352 320c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32s32-14.3 32-32V576h192c70.6 0 128-57.4 128-128s-57.4-128-128-128H352z m288 128c0 35.3-28.7 64-64 64H384V384h192c35.3 0 64 28.7 64 64z" p-id="2591"></path></svg>'
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
const pageContent = getPageContent();
console.log(pageContent);
const style = getStyle();
// 去掉element中的 ck-focused ck-weight_selected消除页面和图片的蓝边
const page = '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>@media print{@page{size:A4 portrait;margin:0cm 3cm}@page:left{margin-left:2.5cm;margin-right:2.7cm;}@page:right{margin-left:2.7cm;margin-right:2.5cm;}}</style>' + style + '</head><body>' + pageContent.replaceAll('ck-focused', 'ck-blurred').replaceAll('ck-weight_selected', '') + '</body></html>'
const newWindow = window.open('', 'PrintDocument', 'height=600,width=700,top=50,left=50');
newWindow.document.write(page);
newWindow.document.close();
newWindow.print();
newWindow.onafterprint = function () {
newWindow.close();
}
});
return button;
});
}
}
// 智能润色插件
class Translation extends Plugin {
init() {
// console.log('Translation initialized!');
this.editor.ui.componentFactory.add('translate', (locale) => {
const dropdownView = createDropdown(locale);
dropdownView.buttonView.set({
label: '智能助手',
withText: true,
});
const items = new Collection();
items.add({
type: 'button',
model: {
id: 'summary',
withText: true,
label: '摘要',
}
});
items.add({
type: 'button',
model: {
id: 'decoration',
withText: true,
label: '润色'
}
});
items.add({
type: 'button',
model: {
id: 'extension',
withText: true,
label: '续写'
}
});
items.add({
type: 'button',
model: {
id: 'correction',
withText: true,
label: '修改'
}
});
items.add({
type: 'button',
model: {
id: 'translation',
withText: true,
label: '翻译'
}
});
addListToDropdown(dropdownView, items);
dropdownView.on('execute', (eventInfo) => {
const { id, label } = eventInfo.source;
// 获取选中的文本,用来进行后续操作
const selectionText = window.getSelection().toString();
if (id === 'summary') {
// this.editor.execute('ExportToWord');
console.log('Object (en):', label, selectionText);
}
});
return dropdownView;
});
}
}
// 侧边栏
class ToggleSideBar extends Plugin{
// constructor(toggleSidebar) {
// super();
// this.toggleSidebar = toggleSidebar;
// }
init() {
const editor = this.editor;
editor.ui.componentFactory.add('SideBar', () => {
// The button will be an instance of ButtonView.
const button = new ButtonView();
button.set({
label: '侧边栏',
// withText: true
tooltip: true,
// 图标 直接插入svg文件
icon: '<svg t="1730903613822" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2614" width="200" height="200"><path d="M849.92 981.333333H175.658667A132.736 132.736 0 0 1 42.666667 848.597333V175.36A132.736 132.736 0 0 1 175.658667 42.666667H849.92C921.898667 42.666667 981.333333 102.016 981.333333 175.402667v673.152C981.333333 922.026667 921.898667 981.333333 849.92 981.333333zM175.658667 136.362667a38.698667 38.698667 0 0 0-39.125334 39.04v673.152c0 21.888 17.194667 39.082667 39.125334 39.082666H849.92a38.698667 38.698667 0 0 0 39.125333-39.04V175.36c-1.578667-21.845333-18.773333-39.04-39.125333-39.04H175.658667z" fill="#172B4D" p-id="2615"></path><path d="M374.314667 957.866667a46.08 46.08 0 0 1-46.933334-46.805334V111.36a46.08 46.08 0 0 1 46.933334-46.890667c26.624 0 46.933333 20.309333 46.933333 46.890667v799.658667a46.08 46.08 0 0 1-46.933333 46.848z" fill="#172B4D" p-id="2616"></path></svg>'
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
// 打开sidebar
const bt = document.getElementById("toggleSidebarButton");
console.log(bt);
bt.click();
});
return button;
});
}
}
export { Export2Word, Export2PDF, Translation, ToggleSideBar };

@ -0,0 +1,149 @@
// utils.js
// 获取用户配置
export async function getUserConfigFromBackend() {
// TODO 请求用户配置
const options = {};
// 字体、字号、样式
// TODO
const {
fontFamilyOptions = [
'default',
'宋体',
'新宋体',
'仿宋',
'楷体',
'微软雅黑',
'黑体',
'华文仿宋',
'华文楷体',
'华文隶书',
'华文宋体',
'华文细黑',
'华文新魏',
'华文行楷',
'华文中宋',
'隶书',
'苹方 常规',
'幼圆',
'Times New Roman'
],
// 五号,小四,四号,小三,三号,小二,二号
fontSizeOptions = [10.5, 12, 14, 15, 'default', 18, 22],
styleDefinitions = [
{
name: 'Article category',
element: 'h3',
classes: ['category']
},
{
name: 'Title',
element: 'h2',
classes: ['document-title']
},
{
name: 'Subtitle',
element: 'h3',
classes: ['document-subtitle']
},
{
name: 'Info box',
element: 'p',
classes: ['info-box']
},
{
name: 'Side quote',
element: 'blockquote',
classes: ['side-quote']
},
{
name: 'Marker',
element: 'span',
classes: ['marker']
},
{
name: 'Spoiler',
element: 'span',
classes: ['spoiler']
},
{
name: 'Code (dark)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-dark']
},
{
name: 'Code (bright)',
element: 'pre',
classes: ['fancy-code', 'fancy-code-bright']
},
{
name: 'GradientBorder',
element: 'p',
classes: ['gradientborder']
}
]
} = options;
// 如果传入的options没有对应项使用默认值
return {
fontFamily: {
options: fontFamilyOptions
},
fontSize: {
options: fontSizeOptions
},
style: {
definitions: styleDefinitions
}
};
}
// 实现自动保存saveData方法将编辑内容发送至后端
export function saveData(data) {
// return new Promise( resolve => {
// setTimeout( () => {
// console.log( 'Saved', data );
// resolve();
// }, HTTP_SERVER_LAG );
// } );
console.log(data);
}
// TODO 手动保存
// function saveByHand(){
// this.editor.plugins.get('Autosave').save().then(() => {
// console.log('Data saved successfully');
// });
// }
// 将当前页面的样式转为内联
export function getStyle() {
let str = '<head><meta charset="utf-8"></meta>';
const styles = document.querySelectorAll('style');
for (let i = 0; i < styles.length; i++) {
str += styles[i].outerHTML;
}
str += "<style>.results{width:100%!important;} .result .title{width:100%;}</style>";
str += "<style>table{border-collapse: collapse;table-layout: fixed}</style>"
// str += "<style>table thead tr{ background-color: #f3f4f9;}</style>"
str += "<style>table td,th{ font-size: 14px;padding: 1px 1px;border-width: 1px;border-style: solid;border-color: #d0d0d0;word-break: keep-all;white-space: nowrap;}</style>"
return str;
}
// 获取用户编辑的内容 <html>
export function getPageContent() {
const pageContent = document.querySelector("#app > div > div > div > div.editor-container__editor-wrapper > div > div > div.ck.ck-reset.ck-editor.ck-rounded-corners > div.ck.ck-editor__main > div");
return pageContent.innerHTML;
}
// 获取并应用用户定义的样式
export async function getAndApplyUserStyles() {
// 模拟从后端获取用户定义的样式
const response = await fetch('/api/user-styles');
const styles = await response.json();
const styleElement = document.createElement('style');
styleElement.innerHTML = styles;
document.head.appendChild(styleElement);
return styles;
}

@ -1,12 +1,12 @@
// import { createApp } from 'vue'
// import App from './App.vue'
// createApp(App).mount('#app')
import { createApp } from 'vue';
import '../public/style.css';
import App from './App.vue';
import { CkeditorPlugin } from '@ckeditor/ckeditor5-vue';
import mitt from 'mitt';
const app = createApp(App);
const emitter = mitt();
createApp(App).use(CkeditorPlugin).mount('#app');
app.config.globalProperties.emitter = emitter;
app.use(CkeditorPlugin);
app.mount('#app');

@ -1,4 +1,21 @@
const { defineConfig } = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = defineConfig({
transpileDependencies: true
transpileDependencies: true,
configureWebpack: {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
}),
]
}
})

Loading…
Cancel
Save