diff --git a/package-lock.json b/package-lock.json index 869f505..8c58b83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,10 @@ "ckplayer": "^3.1.2", "naive-ui": "^2.42.0", "pinia": "^3.0.3", + "quill": "^2.0.3", "vue": "^3.5.17", "vue-i18n": "^9.14.5", + "vue-quill-editor": "^3.0.6", "vue-router": "^4.5.1" }, "devDependencies": { @@ -1833,6 +1835,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -1846,6 +1866,22 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001727", "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", @@ -1873,6 +1909,15 @@ "integrity": "sha512-JHlWTSRm6aqZx+dYdsa6MWz7151omcGBBF9EKK49NL1WCJ2olbdkt7CPKZHvW4lLVgxxEopmuLYEqNdb2cOPhA==", "license": "MIT" }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1988,6 +2033,26 @@ } } }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "license": "MIT", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/default-browser": { "version": "5.2.1", "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.2.1.tgz", @@ -2018,6 +2083,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -2031,6 +2113,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2186,6 +2285,12 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/evtd": { "version": "0.2.4", "resolved": "https://registry.npmmirror.com/evtd/-/evtd-0.2.4.tgz", @@ -2219,6 +2324,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fdir": { "version": "6.4.6", "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.6.tgz", @@ -2325,6 +2442,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2408,6 +2534,18 @@ "dev": true, "license": "ISC" }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", @@ -2482,6 +2620,38 @@ "node": ">=18.18.0" } }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz", @@ -2530,6 +2700,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-4.0.1.tgz", @@ -2656,6 +2844,19 @@ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "license": "MIT" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", @@ -2820,6 +3021,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmmirror.com/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/open": { "version": "10.2.0", "resolved": "https://registry.npmmirror.com/open/-/open-10.2.0.tgz", @@ -2839,6 +3074,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "node_modules/parse-ms": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/parse-ms/-/parse-ms-4.0.0.tgz", @@ -2972,6 +3213,55 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", @@ -3047,6 +3337,38 @@ "semver": "bin/semver.js" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3490,6 +3812,66 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, + "node_modules/vue-quill-editor": { + "version": "3.0.6", + "resolved": "https://registry.npmmirror.com/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz", + "integrity": "sha512-g20oSZNWg8Hbu41Kinjd55e235qVWPLfg4NvsLW6d+DhgBTFbEuMpcWlUdrD6qT3+Noim6DRu18VLM9lVShXOQ==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "quill": "^1.3.4" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/vue-quill-editor/node_modules/eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==", + "license": "MIT" + }, + "node_modules/vue-quill-editor/node_modules/fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", + "license": "Apache-2.0" + }, + "node_modules/vue-quill-editor/node_modules/parchment": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/parchment/-/parchment-1.1.4.tgz", + "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", + "license": "BSD-3-Clause" + }, + "node_modules/vue-quill-editor/node_modules/quill": { + "version": "1.3.7", + "resolved": "https://registry.npmmirror.com/quill/-/quill-1.3.7.tgz", + "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", + "license": "BSD-3-Clause", + "dependencies": { + "clone": "^2.1.1", + "deep-equal": "^1.0.1", + "eventemitter3": "^2.0.3", + "extend": "^3.0.2", + "parchment": "^1.1.4", + "quill-delta": "^3.6.2" + } + }, + "node_modules/vue-quill-editor/node_modules/quill-delta": { + "version": "3.6.3", + "resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-3.6.3.tgz", + "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", + "license": "MIT", + "dependencies": { + "deep-equal": "^1.0.1", + "extend": "^3.0.2", + "fast-diff": "1.1.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/vue-router": { "version": "4.5.1", "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.5.1.tgz", diff --git a/package.json b/package.json index 5c839cf..5645edd 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,10 @@ "ckplayer": "^3.1.2", "naive-ui": "^2.42.0", "pinia": "^3.0.3", + "quill": "^2.0.3", "vue": "^3.5.17", "vue-i18n": "^9.14.5", + "vue-quill-editor": "^3.0.6", "vue-router": "^4.5.1" }, "devDependencies": { diff --git a/public/images/aiCompanion/homework.png b/public/images/aiCompanion/homework.png new file mode 100644 index 0000000..5a45f7c Binary files /dev/null and b/public/images/aiCompanion/homework.png differ diff --git a/public/images/aiCompanion/reply.png b/public/images/aiCompanion/reply.png new file mode 100644 index 0000000..3629f25 Binary files /dev/null and b/public/images/aiCompanion/reply.png differ diff --git a/public/images/aiCompanion/talk.png b/public/images/aiCompanion/talk.png new file mode 100644 index 0000000..d6bf84c Binary files /dev/null and b/public/images/aiCompanion/talk.png differ diff --git a/public/images/courses/@.png b/public/images/courses/@.png new file mode 100644 index 0000000..0c36e96 Binary files /dev/null and b/public/images/courses/@.png differ diff --git a/public/images/courses/Image.png b/public/images/courses/Image.png new file mode 100644 index 0000000..5283732 Binary files /dev/null and b/public/images/courses/Image.png differ diff --git a/public/images/courses/comments-note-active.png b/public/images/courses/comments-note-active.png new file mode 100644 index 0000000..221db41 Binary files /dev/null and b/public/images/courses/comments-note-active.png differ diff --git a/public/images/courses/comments-note.png b/public/images/courses/comments-note.png new file mode 100644 index 0000000..eeeba09 Binary files /dev/null and b/public/images/courses/comments-note.png differ diff --git a/public/images/courses/expression.png b/public/images/courses/expression.png new file mode 100644 index 0000000..1c0652b Binary files /dev/null and b/public/images/courses/expression.png differ diff --git a/public/images/examination/score-bg.png b/public/images/examination/score-bg.png new file mode 100644 index 0000000..1cb49d6 Binary files /dev/null and b/public/images/examination/score-bg.png differ diff --git a/public/images/profile/del-black.png b/public/images/profile/del-black.png new file mode 100644 index 0000000..dd8c0a8 Binary files /dev/null and b/public/images/profile/del-black.png differ diff --git a/public/images/profile/file.png b/public/images/profile/file.png new file mode 100644 index 0000000..23484cc Binary files /dev/null and b/public/images/profile/file.png differ diff --git a/src/components/common/QuillEditor.vue b/src/components/common/QuillEditor.vue new file mode 100644 index 0000000..8e5e7e5 --- /dev/null +++ b/src/components/common/QuillEditor.vue @@ -0,0 +1,480 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index a90e5f0..4bd4e29 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -314,6 +314,22 @@ router.beforeEach((to, from, next) => { } } + // 特殊处理:检测从其他页面进入已兑换页面 + if (to.name === 'CourseExchanged') { + // 如果是从其他页面进入已兑换页面,设置自动刷新标记 + if (from.name && from.name !== 'CourseExchanged') { + sessionStorage.setItem('refreshCourseExchanged', 'true'); + } + } + + // 特殊处理:检测从其他页面进入个人中心 + if (to.name === 'Profile') { + // 如果是从其他页面进入个人中心,设置自动刷新标记 + if (from.name && from.name !== 'Profile') { + sessionStorage.setItem('refreshProfile', 'true'); + } + } + next() }) diff --git a/src/views/AICompanion.vue b/src/views/AICompanion.vue index 4f19c52..a7bf09c 100644 --- a/src/views/AICompanion.vue +++ b/src/views/AICompanion.vue @@ -145,7 +145,7 @@

{{ course.description || '本课程深度聚焦问题,让每一位教师了解并学习使用DeepSeek,结合办公自动化职业岗位标准,以实际工作任务为引导,强调课程内容的易用性和岗位要求的匹配性。课程内容与全国计算机等级考试、"1+X"WPS办公应用职业技能等级证书,技能大赛紧密结合,课程设置紧密对应实际全面共享,可为职业工作人员、在校学生、创行教师提供服务与学习支持。' - }}

+}}

@@ -190,14 +190,36 @@
- +
+
+
+ 用户头像 +
+
+ +
+
+ + + +
+
+ +
+
+
-
--> +
@@ -207,23 +229,161 @@
{{ comment.username }} -
{{ comment.content }}
- + + +
+ + +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
+
+ + +
+ +
+
+ 讲师头像 +
+
+
+
+ 张老师 + 讲师 +
+
感谢您的反馈!我们会继续优化课程内容,让学习体验更好。
+
+ +
+
+ + +
+
+ 用户头像 +
+
+
+
+ 李同学 + 学员 +
+
同意楼上的观点,这个课程确实很有帮助!
+
+ +
+
+
+
+
+ +
+
+ 张老师 +
+
+
+ 张老师 +
+
这个课程内容很实用,讲解得很清楚,对初学者很有帮助!111
+
+ 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 +
+ +6 +
+
+
+
+ 笔记 + 笔记 +
+ 2025.07.23 16:28 + +
+ + +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
- -
@@ -811,7 +971,8 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '2天前', content: '老师讲得很详细,从零基础到实际应用都有涉及,非常适合初学者!', - likes: 23 + likes: 23, + type: 'comment' }, { id: 2, @@ -819,7 +980,8 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '5天前', content: '课程内容很实用,跟着做了几个项目,收获很大。推荐给想学AI的朋友们!', - likes: 18 + likes: 18, + type: 'comment' }, { id: 3, @@ -827,10 +989,102 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '1周前', content: 'DeepSeek确实是个很强大的工具,通过这个课程学会了很多实用技巧。', - likes: 31 + likes: 31, + type: 'comment' } ]) +// 新评论内容 +const newComment = ref('') + +// 自动调整textarea高度 +const adjustTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = 'auto' + textarea.style.height = textarea.scrollHeight + 'px' +} + +// 点击textarea时调整高度 +const handleTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + // 如果当前高度是40px,则调整到60px + if (textarea.style.height === '40px' || textarea.style.height === '') { + textarea.style.height = '60px' + } +} + +// 提交评论函数 +const submitComment = () => { + if (newComment.value.trim()) { + const newCommentObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: newComment.value, + likes: 0, + type: 'comment' + } + displayComments.value.unshift(newCommentObj) + newComment.value = '' + // 这里可以调用API提交评论 + console.log('评论已提交:', newCommentObj) + } +} + +// 回复相关函数 +const startReply = (commentId: number, username: string) => { + replyingTo.value = commentId + replyToUsername.value = username + replyText.value = '' +} + +const cancelReply = () => { + replyingTo.value = null + replyToUsername.value = '' + replyText.value = '' +} + +const submitReply = () => { + if (replyText.value.trim() && replyingTo.value) { + const newReplyObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: replyText.value, + likes: 0 + } + + // 这里可以调用API提交回复 + console.log('回复已提交:', newReplyObj) + console.log('回复给评论ID:', replyingTo.value) + console.log('回复给用户:', replyToUsername.value) + + // 清空回复状态 + cancelReply() + } +} + +// 回复文本框高度调整 +const adjustReplyTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = '40px' + textarea.style.height = textarea.scrollHeight + 'px' +} + +const handleReplyTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + if (textarea.style.height === '40px' || !textarea.style.height) { + textarea.style.height = '60px' + } +} + +// 回复相关数据 +const replyingTo = ref(null) +const replyText = ref('') +const replyToUsername = ref('') + // 加载课程详情 const loadCourseDetail = async () => { console.log('开始加载课程详情,课程ID:', courseId.value) @@ -3821,7 +4075,7 @@ onMounted(() => { .ai-companion-tag { width: 64px; -height: 20px; + height: 20px; display: flex; align-items: center; } @@ -3867,4 +4121,440 @@ height: 20px; font-size: 12px; font-weight: 500; } + +/* 评论区样式 */ +.comments-content { + padding: 0; +} + +/* 发布评论区域 */ +.post-comment-section { + margin-bottom: 10px; +} + +.comment-input-wrapper { + display: flex; + gap: 12px; +} + +.user-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.comment-input-area { + flex: 1; +} + +.comment-textarea { + width: 100%; + border: 1px solid #E6E6E6; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; +} + +.comment-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.comment-textarea::placeholder { + color: #999; +} + +.comment-toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.toolbar-left { + display: flex; + gap: 8px; +} + +.toolbar-btn { + background: none; + border: none; + width: 24px; + height: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border: 1.5px solid #E6E6E6; +} + +.toolbar-btn:hover { + background: #f5f5f5; +} + +.toolbar-icon { + width: 12px; + height: 12px; + object-fit: contain; +} + +.toolbar-right { + display: flex; + align-items: center; +} + +.btn-submit { + background: #0088D1; + color: white; + border: none; + padding: 3px 10px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; + font-weight: 500; +} + +.btn-submit:hover:not(:disabled) { + background: #40a9ff; +} + +.btn-submit:disabled { + opacity: 0.5; + cursor: not-allowed; + background: #f5f5f5; + color: #bfbfbf; +} + +/* 回复输入区域样式 */ +.reply-input-section { + margin-top: 16px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.reply-input-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.reply-to-text { + font-size: 14px; + color: #666; + font-weight: 500; +} + +.cancel-reply-btn { + background: none; + border: none; + color: #999; + font-size: 14px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.3s ease; +} + +.cancel-reply-btn:hover { + background: #f0f0f0; + color: #666; +} + +.reply-input-container { + background: white; + border: 1px solid #E6E6E6; + border-radius: 6px; + overflow: hidden; +} + +.reply-textarea { + width: 100%; + border: none; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; + background: transparent; +} + +.reply-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.reply-textarea::placeholder { + color: #999; +} + +.reply-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + border-top: 1px solid #f0f0f0; + background: #fafafa; +} + +.comment-list { + display: flex; + flex-direction: column; + gap: 20px; +} + +.comment-item { + display: flex; + gap: 12px; +} + +.comment-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; +} + +.comment-content { + flex: 1; +} + +.comment-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.comment-username { + font-size: 14px; + color: #666666; +} + +.comment-time { + font-size: 12px; + color: #999; +} + +.comment-text { + font-size: 14px; + line-height: 1.6; + color: #333; + margin-bottom: 12px; +} + +.comment-image-container { + width: 100%; + margin-bottom: 10px; + display: flex; + flex-wrap: wrap; + gap: 16px; + position: relative; +} + +.comment-image-container img { + width: 84px; + height: 84px; + object-fit: cover; + border-radius: 4px; +} + +.image-overlay { + position: absolute; + top: 0; + left: calc(6 * (84px + 16px)); + width: 84px; + height: 84px; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; +} + +.more-images-text { + color: white; + font-size: 16px; + font-weight: 500; +} + +.comment-actions { + display: flex; + align-items: center; + gap: 16px; +} + +.note-icon-container { + width: 50px; + height: 20px; + background: #EDEDED; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + gap: 4px; +} + +.note-icon-container img { + width: 10px; + height: 10px; +} + +.note-icon-container span { + color: #666666; + font-size: 10px; +} + +.action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + display: flex; + align-items: center; + gap: 14px; + transition: color 0.3s; +} + +.action-btn:hover { + color: #1890ff; +} + +.action-btn span { + font-size: 12px; + color: #999; +} + +.action-btn .top { + padding: 4px 8px; + font-size: 10px; + color: #FF304B; + background-color: #FFF4F4; + border-radius: 30px; +} + +/* 回复和二级评论样式 */ +.comment-replies { + margin-top: 12px; +} + +.reply-item { + display: flex; + gap: 12px; + margin-bottom: 16px; + position: relative; +} + +.reply-item:last-child { + margin-bottom: 0; +} + +.reply-avatar { + flex-shrink: 0; +} + +.reply-avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; +} + +.reply-content { + flex: 1; +} + +.reply-main { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 8px; +} + +.reply-header { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.reply-username { + font-size: 14px; + color: #666; +} + +.reply-badge { + width: 32px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + font-weight: 500; + font-size: 10px; +} + +.reply-badge.instructor { + background: #EEF9FF; + color: #008BD7; +} + +.reply-badge.user { + background: #f6ffed; + color: #52c41a; +} + +.reply-time { + font-size: 12px; + color: #999; +} + +.reply-text { + font-size: 14px; + line-height: 1.5; + color: #333; + flex: 1; +} + +.reply-footer { + display: flex; + justify-content: left; + align-items: center; + margin-top: 8px; + gap: 15px; +} + +.reply-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.reply-action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + transition: color 0.3s; +} + +.reply-action-btn:hover { + color: #1890ff; +} \ No newline at end of file diff --git a/src/views/CourseDetail.vue b/src/views/CourseDetail.vue index bac4820..3a74152 100644 --- a/src/views/CourseDetail.vue +++ b/src/views/CourseDetail.vue @@ -185,6 +185,37 @@
+ +
+
+
+ 用户头像 +
+
+ +
+
+ + + +
+
+ +
+
+
+
+
+ +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
+
+ + +
+ +
+
+ 讲师头像 +
+
+
+
+ 张老师 + 讲师 +
+
感谢您的反馈!我们会继续优化课程内容,让学习体验更好。
+
+ +
+
+ + +
+
+ 用户头像 +
+
+
+
+ 李同学 + 学员 +
+
同意楼上的观点,这个课程确实很有帮助!
+
+ +
+
+
+
+
+ +
+
+ 张老师 +
+
+
+ 张老师 +
+
这个课程内容很实用,讲解得很清楚,对初学者很有帮助!111
+
+ 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 +
+ +6 +
+
+
+
+ 笔记 + 笔记 +
+ 2025.07.23 16:28 + +
+ + +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
@@ -289,7 +460,7 @@
{{ section.name - }} + }}
{ const chapterSections = sections.slice(sectionIndex, sectionIndex + sectionsPerChapter[i]) if (chapterSections.length > 0) { groups.push({ - title: `第${i+1}章 ${chapterTitles[i]}`, + title: `第${i + 1}章 ${chapterTitles[i]}`, sections: chapterSections, expanded: i === 0 // 默认展开第一章 }) @@ -646,7 +817,7 @@ const totalSections = computed(() => { const formatTotalDuration = () => { // 计算总时长 let totalMinutes = 0 - courseSections.value.forEach(section => { + courseSections.value.forEach((section: CourseSection) => { if (section.duration) { const parts = section.duration.split(':') if (parts.length === 3) { @@ -662,6 +833,91 @@ const formatTotalDuration = () => { return `${hours}小时${minutes}分钟` } +// 新评论内容 +const newComment = ref('') + +// 自动调整textarea高度 +const adjustTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = 'auto' + textarea.style.height = textarea.scrollHeight + 'px' +} + +// 点击textarea时调整高度 +const handleTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + // 如果当前高度是40px,则调整到60px + if (textarea.style.height === '40px' || textarea.style.height === '') { + textarea.style.height = '60px' + } +} + +// 提交评论函数 +const submitComment = () => { + if (newComment.value.trim()) { + const newCommentObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: newComment.value, + likes: 0 + } + displayComments.value.unshift(newCommentObj) + newComment.value = '' + // 这里可以调用API提交评论 + console.log('评论已提交:', newCommentObj) + } +} + +// 回复相关函数 +const startReply = (commentId: number, username: string) => { + replyingTo.value = commentId + replyToUsername.value = username + replyText.value = '' +} + +const cancelReply = () => { + replyingTo.value = null + replyToUsername.value = '' + replyText.value = '' +} + +const submitReply = () => { + if (replyText.value.trim() && replyingTo.value) { + const newReplyObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: replyText.value, + likes: 0 + } + + // 这里可以调用API提交回复 + console.log('回复已提交:', newReplyObj) + console.log('回复给评论ID:', replyingTo.value) + console.log('回复给用户:', replyToUsername.value) + + // 清空回复状态 + cancelReply() + } +} + +// 回复文本框高度调整 +const adjustReplyTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = '40px' + textarea.style.height = textarea.scrollHeight + 'px' +} + +const handleReplyTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + if (textarea.style.height === '40px' || !textarea.style.height) { + textarea.style.height = '60px' + } +} + const displayComments = ref([ { id: 1, @@ -689,6 +945,11 @@ const displayComments = ref([ } ]) +// 回复相关数据 +const replyingTo = ref(null) +const replyText = ref('') +const replyToUsername = ref('') + // 加载课程详情 const loadCourseDetail = async () => { console.log('开始加载课程详情,课程ID:', courseId.value) @@ -2554,6 +2815,191 @@ onMounted(() => { padding: 0; } +/* 发布评论区域 */ +.post-comment-section { + margin-bottom: 10px; +} + +.comment-input-wrapper { + display: flex; + gap: 12px; +} + +.user-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.comment-input-area { + flex: 1; +} + +.comment-textarea { + width: 100%; + border: 1px solid #E6E6E6; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; +} + +.comment-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.comment-textarea::placeholder { + color: #999; +} + +.comment-toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.toolbar-left { + display: flex; + gap: 8px; +} + +.toolbar-btn { + background: none; + border: none; + width: 24px; + height: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border: 1.5px solid #E6E6E6; +} + +.toolbar-btn:hover { + background: #f5f5f5; +} + +.toolbar-icon { + width: 12px; + height: 12px; + object-fit: contain; +} + +.toolbar-right { + display: flex; + align-items: center; +} + +.btn-submit { + background: #0088D1; + color: white; + border: none; + padding: 3px 10px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; + font-weight: 500; +} + +.btn-submit:hover:not(:disabled) { + background: #40a9ff; +} + +.btn-submit:disabled { + opacity: 0.5; + cursor: not-allowed; + background: #f5f5f5; + color: #bfbfbf; +} + +/* 回复输入区域样式 */ +.reply-input-section { + margin-top: 16px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.reply-input-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.reply-to-text { + font-size: 14px; + color: #666; + font-weight: 500; +} + +.cancel-reply-btn { + background: none; + border: none; + color: #999; + font-size: 14px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.3s ease; +} + +.cancel-reply-btn:hover { + background: #f0f0f0; + color: #666; +} + +.reply-input-container { + background: white; + border: 1px solid #E6E6E6; + border-radius: 6px; + overflow: hidden; +} + +.reply-textarea { + width: 100%; + border: none; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; + background: transparent; +} + +.reply-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.reply-textarea::placeholder { + color: #999; +} + +.reply-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + border-top: 1px solid #f0f0f0; + background: #fafafa; +} + .comment-stats { display: flex; justify-content: space-between; @@ -2617,13 +3063,13 @@ onMounted(() => { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 8px; + /* margin-bottom: 8px; */ } .comment-username { font-size: 14px; - font-weight: 600; - color: #333; + /* font-weight: 600; */ + color: #666666; } .comment-time { @@ -2634,16 +3080,73 @@ onMounted(() => { .comment-text { font-size: 14px; line-height: 1.6; - color: #666; + color: #333; margin-bottom: 12px; } +.comment-image-container { + width: 100%; + margin-bottom: 10px; + display: flex; + flex-wrap: wrap; + gap: 16px; + position: relative; +} + +.comment-image-container img { + width: 84px; + height: 84px; + object-fit: cover; + border-radius: 4px; +} + +.image-overlay { + position: absolute; + top: 0; + left: calc(6 * (84px + 16px)); + width: 84px; + height: 84px; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; +} + +.more-images-text { + color: white; + font-size: 16px; + font-weight: 500; +} + .comment-actions { display: flex; align-items: center; gap: 16px; } +.note-icon-container { + width: 50px; + height: 20px; + background: #EDEDED; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + gap: 4px; +} + +.note-icon-container img { + width: 10px; + height: 10px; +} + +.note-icon-container span { + color: #666666; + font-size: 10px; +} + .action-btn { background: none; border: none; @@ -2692,6 +3195,131 @@ onMounted(() => { background: #d9d9d9; } +/* 回复和二级评论样式 */ +.comment-replies { + margin-top: 12px; +} + +.reply-item { + display: flex; + gap: 12px; + margin-bottom: 16px; + position: relative; +} + +.reply-item:last-child { + margin-bottom: 0; +} + +.reply-avatar { + flex-shrink: 0; +} + +.reply-avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; +} + +.reply-content { + flex: 1; +} + +.reply-main { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 8px; +} + +.reply-header { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.reply-username { + font-size: 14px; + color: #666; +} + +.reply-badge { + width: 32px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + font-weight: 500; + font-size: 10px; +} + +.reply-badge.instructor { + background: #EEF9FF; + color: #008BD7; +} + +.reply-badge.user { + background: #f6ffed; + color: #52c41a; +} + +.reply-time { + font-size: 12px; + color: #999; +} + +.reply-text { + font-size: 14px; + line-height: 1.5; + color: #333; + flex: 1; +} + +.reply-footer { + display: flex; + justify-content: left; + align-items: center; + margin-top: 8px; + gap: 15px; +} + +.reply-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.reply-action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + transition: color 0.3s; + padding: 0; +} + +.reply-action-btn:hover { + color: #1890ff; +} + +/* 讲师评论特殊样式 */ +.reply-item.instructor-reply {} + +.reply-item.instructor-reply .reply-username { + color: #666666; + font-weight: 500; +} + +/* 用户评论样式 */ +.reply-item.user-reply {} + +.reply-item.user-reply .reply-username { + color: #666666; + font-weight: 500; +} /* 右侧边栏 */ .sidebar { display: flex; @@ -2936,6 +3564,7 @@ onMounted(() => { padding-left: 24px; padding-right: 24px; } + /* 响应式设计 */ @media (max-width: 1399px) and (min-width: 1200px) { .container { diff --git a/src/views/CourseDetailEnrolled.vue b/src/views/CourseDetailEnrolled.vue index 06ae51a..942e3c3 100644 --- a/src/views/CourseDetailEnrolled.vue +++ b/src/views/CourseDetailEnrolled.vue @@ -60,13 +60,9 @@
-
+ @click="changeVideoQuality(quality.value); showQualityMenu = false"> {{ quality.label }}
@@ -185,14 +181,36 @@
- +
+
+
+ 用户头像 +
+
+ +
+
+ + + +
+
+ +
+
+
-
--> +
@@ -202,23 +220,161 @@
{{ comment.username }} - {{ comment.time }}
{{ comment.content }}
- + + +
+ + +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
+
+ + +
+ +
+
+ 讲师头像 +
+
+
+
+ 张老师 + 讲师 +
+
感谢您的反馈!我们会继续优化课程内容,让学习体验更好。
+
+ +
+
+ + +
+
+ 用户头像 +
+
+
+
+ 李同学 + 学员 +
+
同意楼上的观点,这个课程确实很有帮助!
+
+ +
+
+
+
+
+ +
+
+ 张老师 +
+
+
+ 张老师 +
+
这个课程内容很实用,讲解得很清楚,对初学者很有帮助!111
+
+ 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 + 课程图片 +
+ +6 +
+
+
+
+ 笔记 + 笔记 +
+ 2025.07.23 16:28 + +
+ + +
+
+ 回复 @{{ replyToUsername }} + +
+
+ +
+
+ + + +
+
+ +
+
+
- -
@@ -544,7 +700,8 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '2天前', content: '老师讲得很详细,从零基础到实际应用都有涉及,非常适合初学者!', - likes: 23 + likes: 23, + type: 'comment' }, { id: 2, @@ -552,7 +709,8 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '5天前', content: '课程内容很实用,跟着做了几个项目,收获很大。推荐给想学AI的朋友们!', - likes: 18 + likes: 18, + type: 'comment' }, { id: 3, @@ -560,10 +718,102 @@ const displayComments = ref([ avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&auto=format&fit=crop&w=50&q=80', time: '1周前', content: 'DeepSeek确实是个很强大的工具,通过这个课程学会了很多实用技巧。', - likes: 31 + likes: 31, + type: 'comment' } ]) +// 新评论内容 +const newComment = ref('') + +// 自动调整textarea高度 +const adjustTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = 'auto' + textarea.style.height = textarea.scrollHeight + 'px' +} + +// 点击textarea时调整高度 +const handleTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + // 如果当前高度是40px,则调整到60px + if (textarea.style.height === '40px' || textarea.style.height === '') { + textarea.style.height = '60px' + } +} + +// 提交评论函数 +const submitComment = () => { + if (newComment.value.trim()) { + const newCommentObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: newComment.value, + likes: 0, + type: 'comment' + } + displayComments.value.unshift(newCommentObj) + newComment.value = '' + // 这里可以调用API提交评论 + console.log('评论已提交:', newCommentObj) + } +} + +// 回复相关函数 +const startReply = (commentId: number, username: string) => { + replyingTo.value = commentId + replyToUsername.value = username + replyText.value = '' +} + +const cancelReply = () => { + replyingTo.value = null + replyToUsername.value = '' + replyText.value = '' +} + +const submitReply = () => { + if (replyText.value.trim() && replyingTo.value) { + const newReplyObj = { + id: Date.now(), + username: '当前用户', + avatar: 'https://via.placeholder.com/40x40/1890ff/ffffff?text=我', + time: '刚刚', + content: replyText.value, + likes: 0 + } + + // 这里可以调用API提交回复 + console.log('回复已提交:', newReplyObj) + console.log('回复给评论ID:', replyingTo.value) + console.log('回复给用户:', replyToUsername.value) + + // 清空回复状态 + cancelReply() + } +} + +// 回复文本框高度调整 +const adjustReplyTextareaHeight = (event: Event) => { + const textarea = event.target as HTMLTextAreaElement + textarea.style.height = '40px' + textarea.style.height = textarea.scrollHeight + 'px' +} + +const handleReplyTextareaClick = (event: MouseEvent) => { + const textarea = event.target as HTMLTextAreaElement + if (textarea.style.height === '40px' || !textarea.style.height) { + textarea.style.height = '60px' + } +} + +// 回复相关数据 +const replyingTo = ref(null) +const replyText = ref('') +const replyToUsername = ref('') + // 生成模拟章节数据(暂时禁用) const generateMockSections = (): CourseSection[] => { // 暂时返回空数组,等待API修复 @@ -1232,7 +1482,6 @@ onUnmounted(() => { .video-player { background: #000; overflow: hidden; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .video-container { @@ -1566,7 +1815,6 @@ onUnmounted(() => { .course-tabs { padding: 14px 24px; background-color: #ffffff; - box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); margin-bottom: 40px; } @@ -2905,4 +3153,440 @@ onUnmounted(() => { font-size: 14px; } } + +/* 评论区样式 */ +.comments-content { + padding: 0; +} + +/* 发布评论区域 */ +.post-comment-section { + margin-bottom: 10px; +} + +.comment-input-wrapper { + display: flex; + gap: 12px; +} + +.user-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.comment-input-area { + flex: 1; +} + +.comment-textarea { + width: 100%; + border: 1px solid #E6E6E6; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; +} + +.comment-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.comment-textarea::placeholder { + color: #999; +} + +.comment-toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.toolbar-left { + display: flex; + gap: 8px; +} + +.toolbar-btn { + background: none; + border: none; + width: 24px; + height: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border: 1.5px solid #E6E6E6; +} + +.toolbar-btn:hover { + background: #f5f5f5; +} + +.toolbar-icon { + width: 12px; + height: 12px; + object-fit: contain; +} + +.toolbar-right { + display: flex; + align-items: center; +} + +.btn-submit { + background: #0088D1; + color: white; + border: none; + padding: 3px 10px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; + font-weight: 500; +} + +.btn-submit:hover:not(:disabled) { + background: #40a9ff; +} + +.btn-submit:disabled { + opacity: 0.5; + cursor: not-allowed; + background: #f5f5f5; + color: #bfbfbf; +} + +/* 回复输入区域样式 */ +.reply-input-section { + margin-top: 16px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.reply-input-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.reply-to-text { + font-size: 14px; + color: #666; + font-weight: 500; +} + +.cancel-reply-btn { + background: none; + border: none; + color: #999; + font-size: 14px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.3s ease; +} + +.cancel-reply-btn:hover { + background: #f0f0f0; + color: #666; +} + +.reply-input-container { + background: white; + border: 1px solid #E6E6E6; + border-radius: 6px; + overflow: hidden; +} + +.reply-textarea { + width: 100%; + border: none; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; + background: transparent; +} + +.reply-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.reply-textarea::placeholder { + color: #999; +} + +.reply-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + border-top: 1px solid #f0f0f0; + background: #fafafa; +} + +.comment-list { + display: flex; + flex-direction: column; + gap: 20px; +} + +.comment-item { + display: flex; + gap: 12px; +} + +.comment-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; +} + +.comment-content { + flex: 1; +} + +.comment-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.comment-username { + font-size: 14px; + color: #666666; +} + +.comment-time { + font-size: 12px; + color: #999; +} + +.comment-text { + font-size: 14px; + line-height: 1.6; + color: #333; + margin-bottom: 12px; +} + +.comment-image-container { + width: 100%; + margin-bottom: 10px; + display: flex; + flex-wrap: wrap; + gap: 16px; + position: relative; +} + +.comment-image-container img { + width: 84px; + height: 84px; + object-fit: cover; + border-radius: 4px; +} + +.image-overlay { + position: absolute; + top: 0; + left: calc(6 * (84px + 16px)); + width: 84px; + height: 84px; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; +} + +.more-images-text { + color: white; + font-size: 16px; + font-weight: 500; +} + +.comment-actions { + display: flex; + align-items: center; + gap: 16px; +} + +.note-icon-container { + width: 50px; + height: 20px; + background: #EDEDED; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + gap: 4px; +} + +.note-icon-container img { + width: 10px; + height: 10px; +} + +.note-icon-container span { + color: #666666; + font-size: 10px; +} + +.action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + display: flex; + align-items: center; + gap: 14px; + transition: color 0.3s; +} + +.action-btn:hover { + color: #1890ff; +} + +.action-btn span { + font-size: 12px; + color: #999; +} + +.action-btn .top { + padding: 4px 8px; + font-size: 10px; + color: #FF304B; + background-color: #FFF4F4; + border-radius: 30px; +} + +/* 回复和二级评论样式 */ +.comment-replies { + margin-top: 12px; +} + +.reply-item { + display: flex; + gap: 12px; + margin-bottom: 16px; + position: relative; +} + +.reply-item:last-child { + margin-bottom: 0; +} + +.reply-avatar { + flex-shrink: 0; +} + +.reply-avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; +} + +.reply-content { + flex: 1; +} + +.reply-main { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 8px; +} + +.reply-header { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.reply-username { + font-size: 14px; + color: #666; +} + +.reply-badge { + width: 32px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + font-weight: 500; + font-size: 10px; +} + +.reply-badge.instructor { + background: #EEF9FF; + color: #008BD7; +} + +.reply-badge.user { + background: #f6ffed; + color: #52c41a; +} + +.reply-time { + font-size: 12px; + color: #999; +} + +.reply-text { + font-size: 14px; + line-height: 1.5; + color: #333; + flex: 1; +} + +.reply-footer { + display: flex; + justify-content: left; + align-items: center; + margin-top: 8px; + gap: 15px; +} + +.reply-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.reply-action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + transition: color 0.3s; +} + +.reply-action-btn:hover { + color: #1890ff; +} diff --git a/src/views/CourseExchanged.vue b/src/views/CourseExchanged.vue index 385ec82..efa525f 100644 --- a/src/views/CourseExchanged.vue +++ b/src/views/CourseExchanged.vue @@ -1,5 +1,12 @@ @@ -3798,6 +4204,7 @@ onMounted(() => { } .toolbar { + margin-top: 15px; margin-left: 16px; padding: 0; } @@ -3828,8 +4235,7 @@ onMounted(() => { /* AI内容区域 */ .ai-content-area { - background-color: #fff; - padding: 15px; + /* background-color: #fff; */ margin-bottom: 20px; } @@ -3837,13 +4243,13 @@ onMounted(() => { .ai-chat-interface { display: flex; flex-direction: column; - height: 400px; + height: 600px; } .chat-messages { flex: 1; overflow-y: auto; - padding: 10px 0; + padding: 10px; display: flex; flex-direction: column; gap: 16px; @@ -3851,6 +4257,7 @@ onMounted(() => { scrollbar-width: none; /* Firefox */ -ms-overflow-style: none; + background-color: #fff; /* IE and Edge */ } @@ -4130,6 +4537,73 @@ onMounted(() => { color: #1890ff; } +/* 笔记编辑器样式 */ +.note-editor-container { + background: white; + border-radius: 8px; + padding: 16px; + margin-bottom: 16px; + border: 1px solid #e8e8e8; +} + +.note-editor-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + gap: 12px; +} + +.note-title-input { + flex: 1; + padding: 8px 12px; + border: 1px solid #e0e0e0; + border-radius: 4px; + font-size: 14px; + outline: none; + transition: border-color 0.2s; +} + +.note-title-input:focus { + border-color: #1890ff; +} + +.note-editor-actions { + display: flex; + gap: 8px; +} + +.save-note-btn { + background: #1890ff; + color: white; + border: none; + padding: 6px 12px; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + transition: background-color 0.3s; +} + +.save-note-btn:hover { + background: #40a9ff; +} + +.cancel-note-btn { + background: #f5f5f5; + color: #666; + border: 1px solid #d9d9d9; + padding: 6px 12px; + border-radius: 4px; + font-size: 12px; + cursor: pointer; + transition: all 0.3s; +} + +.cancel-note-btn:hover { + background: #e6e6e6; + border-color: #bfbfbf; +} + .ai-text-content { margin-bottom: 16px; } @@ -5100,4 +5574,540 @@ onMounted(() => { .ai-tab-item:not(.active):hover { background: rgba(0, 0, 0, 0.05); } + +/* 评论区样式 */ +.comments-content { + padding: 0; +} + +/* 发布评论区域 */ +.post-comment-section { + margin-bottom: 10px; +} + +.comment-input-wrapper { + display: flex; + gap: 12px; +} + +.user-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + flex-shrink: 0; +} + +.comment-input-area { + flex: 1; +} + +.comment-textarea { + width: 100%; + border: 1px solid #E6E6E6; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; +} + +.comment-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.comment-textarea::placeholder { + color: #999; +} + +.comment-toolbar { + display: flex; + justify-content: space-between; + align-items: center; +} + +.toolbar-left { + display: flex; + gap: 8px; +} + +.toolbar-btn { + background: none; + border: none; + width: 24px; + height: 20px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + border: 1.5px solid #E6E6E6; +} + +.toolbar-btn:hover { + background: #f5f5f5; +} + +.toolbar-icon { + width: 12px; + height: 12px; + object-fit: contain; +} + +.toolbar-right { + display: flex; + align-items: center; +} + +.btn-submit { + background: #0088D1; + color: white; + border: none; + padding: 3px 10px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; + font-weight: 500; +} + +.btn-submit:hover:not(:disabled) { + background: #40a9ff; +} + +.btn-submit:disabled { + opacity: 0.5; + cursor: not-allowed; + background: #f5f5f5; + color: #bfbfbf; +} + +/* 回复输入区域样式 */ +.reply-input-section { + margin-top: 16px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.reply-input-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; +} + +.reply-to-text { + font-size: 14px; + color: #666; + font-weight: 500; +} + +.cancel-reply-btn { + background: none; + border: none; + color: #999; + font-size: 14px; + cursor: pointer; + padding: 4px 8px; + border-radius: 4px; + transition: all 0.3s ease; +} + +.cancel-reply-btn:hover { + background: #f0f0f0; + color: #666; +} + +.reply-input-container { + background: white; + border: 1px solid #E6E6E6; + border-radius: 6px; + overflow: hidden; +} + +.reply-textarea { + width: 100%; + border: none; + padding: 10px; + font-size: 14px; + resize: none; + font-family: inherit; + height: 40px; + min-height: 40px; + box-sizing: border-box; + overflow: hidden; + transition: height 0.3s ease; + background: transparent; +} + +.reply-textarea:focus { + outline: none; + border-color: #1890ff; + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); +} + +.reply-textarea::placeholder { + color: #999; +} + +.reply-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 10px; + border-top: 1px solid #f0f0f0; + background: #fafafa; +} + +.comment-list { + display: flex; + flex-direction: column; + gap: 20px; +} + +.comment-item { + display: flex; + gap: 12px; +} + +.comment-avatar img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; +} + +.comment-content { + flex: 1; +} + +.comment-header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.comment-username { + font-size: 14px; + color: #666666; +} + +.comment-time { + font-size: 12px; + color: #999; +} + +.comment-text { + font-size: 14px; + line-height: 1.6; + color: #333; + margin-bottom: 12px; +} + +.comment-image-container { + width: 100%; + margin-bottom: 10px; + display: flex; + flex-wrap: wrap; + gap: 16px; + position: relative; +} + +.comment-image-container img { + width: 84px; + height: 84px; + object-fit: cover; + border-radius: 4px; +} + +.image-overlay { + position: absolute; + top: 0; + left: calc(6 * (84px + 16px)); + width: 84px; + height: 84px; + background: rgba(0, 0, 0, 0.6); + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; +} + +.more-images-text { + color: white; + font-size: 16px; + font-weight: 500; +} + +.comment-actions { + display: flex; + align-items: center; + gap: 16px; +} + +.note-icon-container { + width: 50px; + height: 20px; + background: #EDEDED; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + gap: 4px; +} + +.note-icon-container img { + width: 10px; + height: 10px; +} + +.note-icon-container span { + color: #666666; + font-size: 10px; +} + +.action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + display: flex; + align-items: center; + gap: 14px; + transition: color 0.3s; +} + +.action-btn:hover { + color: #1890ff; +} + +.action-btn span { + font-size: 12px; + color: #999; +} + +.action-btn .top { + padding: 4px 8px; + font-size: 10px; + color: #FF304B; + background-color: #FFF4F4; + border-radius: 30px; +} + +/* 回复和二级评论样式 */ +.comment-replies { + margin-top: 12px; +} + +.reply-item { + display: flex; + gap: 12px; + margin-bottom: 16px; + position: relative; +} + +.reply-item:last-child { + margin-bottom: 0; +} + +.reply-avatar { + flex-shrink: 0; +} + +.reply-avatar img { + width: 24px; + height: 24px; + border-radius: 50%; + object-fit: cover; +} + +.reply-content { + flex: 1; +} + +.reply-main { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 8px; +} + +.reply-header { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.reply-username { + font-size: 14px; + color: #666; +} + +.reply-badge { + width: 32px; + height: 20px; + text-align: center; + line-height: 20px; + font-size: 10px; + font-weight: 500; + font-size: 10px; +} + +.reply-badge.instructor { + background: #EEF9FF; + color: #008BD7; +} + +.reply-badge.user { + background: #f6ffed; + color: #52c41a; +} + +.reply-time { + font-size: 12px; + color: #999; +} + +.reply-text { + font-size: 14px; + line-height: 1.5; + color: #333; + flex: 1; +} + +.reply-footer { + display: flex; + justify-content: left; + align-items: center; + margin-top: 8px; + gap: 15px; +} + +.reply-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.reply-action-btn { + background: none; + border: none; + font-size: 12px; + color: #999; + cursor: pointer; + transition: color 0.3s; +} + +.reply-action-btn:hover { + color: #1890ff; +} + +/* 刷新遮罩样式 */ +.refresh-mask { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.9); + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; + backdrop-filter: blur(2px); +} + +.refresh-content { + text-align: center; + color: #666; +} + +.refresh-spinner { + width: 40px; + height: 40px; + border: 3px solid #f3f3f3; + border-top: 3px solid #1890ff; + border-radius: 50%; + animation: spin 1s linear infinite; + margin: 0 auto 16px; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +/* AI建议样式 */ +.ai-suggestion { + margin-top: 20px; + padding: 20px; + background: white; + border-radius: 8px; +} + +.ai-suggestion-title { + font-size: 14px; + color: #323232; + font-weight: 500; + margin-bottom: 20px; +} + +.ai-suggestion-item { + margin-bottom: 30px; +} + +.ai-suggestion-header { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin-bottom: 8px; +} + +.ai-icon { + width: 18px; + height: 18px; +} + +.ai-category { + font-size: 16px; + color: #323232; + font-weight: 500; +} + +.ai-prompt-bubble { + height: 36px; + line-height: 36px; + background: linear-gradient(90deg, #FFFBD9 0%, #EAF8FF 100%); + border-radius: 2px; + padding: 0 16px; + font-size: 14px; + color: #323232; + cursor: pointer; + transition: all 0.2s; +} + +.ai-prompt-bubble:hover { + background: #e0f2fe; + border-color: #0284c7; +} + +.refresh-content p { + font-size: 16px; + margin: 0; +} \ No newline at end of file diff --git a/src/views/Practice.vue b/src/views/Practice.vue index c4578b0..1e93436 100644 --- a/src/views/Practice.vue +++ b/src/views/Practice.vue @@ -55,7 +55,7 @@

练习题目

{{ String(currentQuestionIndex + 1).padStart(2, '0') }}/{{ - String(questions.length).padStart(2, '0') }} + String(questions.length).padStart(2, '0') }}
@@ -430,40 +430,84 @@