From fbf783582d51d2f9b17fbc700873e2c301e90118 Mon Sep 17 00:00:00 2001 From: Wxp Date: Mon, 18 Aug 2025 12:03:30 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E5=AE=8C=E5=96=84=E7=BB=83=E4=B9=A0?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 382 ++++++ package.json | 2 + public/images/aiCompanion/homework.png | Bin 0 -> 1110 bytes public/images/aiCompanion/reply.png | Bin 0 -> 1101 bytes public/images/aiCompanion/talk.png | Bin 0 -> 1175 bytes public/images/courses/@.png | Bin 0 -> 1301 bytes public/images/courses/Image.png | Bin 0 -> 858 bytes .../images/courses/comments-note-active.png | Bin 0 -> 594 bytes public/images/courses/comments-note.png | Bin 0 -> 547 bytes public/images/courses/expression.png | Bin 0 -> 1172 bytes public/images/examination/score-bg.png | Bin 0 -> 9256 bytes public/images/profile/del-black.png | Bin 0 -> 1034 bytes public/images/profile/file.png | Bin 0 -> 3830 bytes src/components/common/QuillEditor.vue | 480 +++++++ src/router/index.ts | 16 + src/views/AICompanion.vue | 728 ++++++++++- src/views/CourseDetail.vue | 645 +++++++++- src/views/CourseDetailEnrolled.vue | 734 ++++++++++- src/views/CourseExchanged.vue | 1116 ++++++++++++++++- src/views/Practice.vue | 451 +++++-- src/views/Profile.vue | 322 ++++- 21 files changed, 4605 insertions(+), 271 deletions(-) create mode 100644 public/images/aiCompanion/homework.png create mode 100644 public/images/aiCompanion/reply.png create mode 100644 public/images/aiCompanion/talk.png create mode 100644 public/images/courses/@.png create mode 100644 public/images/courses/Image.png create mode 100644 public/images/courses/comments-note-active.png create mode 100644 public/images/courses/comments-note.png create mode 100644 public/images/courses/expression.png create mode 100644 public/images/examination/score-bg.png create mode 100644 public/images/profile/del-black.png create mode 100644 public/images/profile/file.png create mode 100644 src/components/common/QuillEditor.vue 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 0000000000000000000000000000000000000000..5a45f7c8c5726a4d780b6ff79cfb191d442a47e1 GIT binary patch literal 1110 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 LNkvXXu0mjfF4JTC literal 0 HcmV?d00001 diff --git a/public/images/courses/Image.png b/public/images/courses/Image.png new file mode 100644 index 0000000000000000000000000000000000000000..5283732874dbf09e658ad01d97f8fee3e95b0507 GIT binary patch literal 858 zcmV-g1Eu_lP)r9{+VB zNT{h1=ti>U_0_=Z?}4k|xHzrA6zO2#6p>40E~-)o71hYeEnZwip;JWwLfHkUMWlwg z21%PLYcZq5G);YB+%k%ckaNTR>nlHo%OnF_I6DZ1CK=c6^)}e-|DdH77#>60?KFplJVfh57`4F5Iy9Q{5 zSravy?=5gr0?V7ne}r$) z6g>VPaQj`5bLAL;%^(s9T$8Kue%oD+sU<=zdX+j1i1Y9UdT`}U4i=i%FQ1wFP_c=j z^(@$mcia2X=G#bLlcfZ$FV`Vw<`E!{0tg~1D$r!DBgtVv%m6r!(66UxAIj&dt62CJ zV|+c;HYlQu_B2WM!zg^THHi~k8ruMqX@CO`GBeFja{$fe7qmf=K19?~+Eakoi?A`k z;0wscgh+7$c={S|@17<(y?4ieV2Rp8!z+ zz(90yTnn`>4fd}jsw7FX9suG55L+1>Ml`Yy4J99GCrV?{XUxs>Q-}w#WHoQt$(XGx zAyhalZrxczfF}?+isj+9Grx*A>?W`B8QMuDzJpmqB^*0`CLOgr z=n_#rXlHp&r0Cyh>%*+1W97tfORa=gtTdF(gX>CWb+^fHzAmf7CS0}h+-pHXeIsu zcG`%I;LQ3!L@dP02M9h`)Sc^huIu`kb$nG`=C|iN_uO;#US{rb&^j51>t{%g1Se3x z82d2f zsoucNRO$|Kt+Dvz9rGSTOdGPhebnnP=4ZH|aKDTep0xLg|NPgYx)5+`DW}j7A3>^m zhlP8YSsN~BxOuL$Ps`i`h_v&CHCt5wo4#*jVoGV3N&azEmxc@G!`3uZY$Ch&2qk$` z|9`$^W9R%t7t|y@PJQ(n6xBKx!Nmn5l8c3IW5KhZO|f$w&(-km&s&UX)ame%PkuJK zBARW67Y>nCT6^`>UY7|ZtKM1!Y%aKQ!O%v+M-DBCm=H)IY67dZV8F|Erx3Wj(7suL z)JVx;id51rX+e+TJ6x}e4WN_7pCZ6BtKCfJY3ntzqX^dnxnO{{9Cypc;QB+C1|Xl=01`YzxdkR+{Zm#FNX@WI1NifD3?lEjhTR^oXgiRNH5~u|0RR7YzhJTe g000I_L_t&o01U@11pNgyv_xwNEiRH8_L~YCBBaI$B1%QWh8p_=+G>%OhDd6N zCds8A7*q~X&pzkzk|$hEaZ2vzopbIz=j*-izI*jRATSsV2Cv~8Oa~IH_#!8$*+2YM zIJZMhcez{#1f38o7K?k>tbo6-g0X$L0L|y~wPIIbI1~zvU^Sh`AcZ@LL}DhHOwJMC z65oigg1mXikf*ubZa=mI9;sQzT7m|%{FI;`yk4(?$RahTumPhieL!Z2Uw`v>JmXaL zz!n_B3oNMwT?~{O?`8_tY^Ht(bX}jo&#?S6C@@>uiwTurkwmNc{r+|mw_(#}I~)$T z$)IVPE!YRJ8m~?K7L}ltAdgfk^@iI^RfoGe7^i|_e!D_{-vHvMp z_SvYG<>(vcW4;sUTLr>Y@D4H{15u?ZJw}7LFuoROLl)updbbf3yMY=jqY;k zeREPQUj$8#RddFgu!7hi$wq%{-6FpkOX z&gF7xYEPKdB=HfKhAz%4!8Ag%*lt056sM*Qq^BX?^00960 l6o0;`00006NklM*}sj`IKj002ovPDHLkV1g|%^_~C# literal 0 HcmV?d00001 diff --git a/public/images/courses/expression.png b/public/images/courses/expression.png new file mode 100644 index 0000000000000000000000000000000000000000..1c0652beaafe57a2cf9740eec74da355305a4788 GIT binary patch literal 1172 zcmV;F1Z(?=P)(c&Y(Un+bW}-stLJ*=0X$MKb2~Fnq`_6rD=Dqw3Z7Chjx%b?2zVm(WzW46T zM7YDB8xx$Y4WZiDgKGT@{StjHcE!xGCd>_7d~d-@<8cz7L*y<2eu{ig(}(CAVpq%@ zYr<6P=b#=I*Rs_G_fO|gt$hmTe`4bpy-C5Z;oMHN{V@LT+i0%X`{%6&5Q8!6QLi}I zxZG9>RvLpCxbFwRy$xUi9u?r)LnswqLviF3CJLAF!6WnLipzzQRujgs>`|{c#6^;{ zWd(Ir&YvJ)ls*d=J%w_90;R40aoyX55mr6GEWxAP?FopJi^Q^m1A`y4FiM}rqJIL# zM=vtIIa7~%6Vbrg;pht5!**}6(&Em>vA3YBT{nsbLBY`UTs3FK5Rigb$+DdsuaVY7=) z+ngR;ZoMr%25eq!NNNc-jq&(CEWK&Of_Tu9OYPrn&J68#Sh{!)tL&K65^SpK@msty zjYRMPOD^R8wmCg4G-u%OEpO?ObUG8e_7TGfn<;S75k8e`$ffXtT|?b8y%a)0svr=+0Qu zx8vhst1x`>M?b2KW2n^M2#Hn3YU54A2)n%O@N7s0jUedavjU#S>cx8lARg!E?%}a{ zi7&+$m}{#F$Jk7~_i7gkiB`;&9l_wU4A>%Ip9n6XULx3t!@{+z=dIB*6i5 z#mcGHMFQ#-2lVaakHWYEpev|#tN9M6Y5FGQ+>a}E`tFviJd?*s@VgFuV` literal 0 HcmV?d00001 diff --git a/public/images/examination/score-bg.png b/public/images/examination/score-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..1cb49d625ec0c26a8a7275585752564d7ad92a38 GIT binary patch literal 9256 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 KMNUMnLSTY<6z2H= literal 0 HcmV?d00001 diff --git a/public/images/profile/del-black.png b/public/images/profile/del-black.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8c0a805461c0a818ce80738cac7ae24d65718f GIT binary patch literal 1034 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 literal 0 HcmV?d00001 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 @@