From 11be3b5e3ac4cb84abeee91d320ce91931f47163 Mon Sep 17 00:00:00 2001
From: ember <1279347317@qq.com>
Date: Thu, 4 Dec 2025 18:50:15 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=86=99UI=EF=BC=8C=E8=BF=9B=E8=A1=8C?=
=?UTF-8?q?=E5=93=8D=E5=BA=94=E5=BC=8F=E6=94=B9=E9=80=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +
dist/css/app.387e87f6.css | 1 +
dist/css/app.4157a502.css | 1 -
dist/index.html | 2 +-
dist/js/app.2c83ed37.js | 2 +
dist/js/app.728d115f.js | 2 -
src/App.vue | 206 +++----
src/components/NavBar.vue | 388 ++++++++++++
src/router/index.js | 9 +
src/views/AboutPage.vue | 21 +
src/views/ChatList.vue | 54 +-
src/views/CourseDetail.vue | 1001 +++++++++++++++++++++++++++++++
src/views/CourseDetailModal.vue | 163 +++--
src/views/CourseList.vue | 962 ++++++++++++++++-------------
src/views/HomePage.vue | 6 +
src/views/RatingPage.vue | 714 ++++++++++++++--------
src/views/RatingPageforComp.vue | 732 +++++++++++++---------
17 files changed, 3120 insertions(+), 1146 deletions(-)
create mode 100644 dist/css/app.387e87f6.css
delete mode 100644 dist/css/app.4157a502.css
create mode 100644 dist/js/app.2c83ed37.js
delete mode 100644 dist/js/app.728d115f.js
create mode 100644 src/components/NavBar.vue
create mode 100644 src/views/CourseDetail.vue
diff --git a/.gitignore b/.gitignore
index 28acefe..bd695dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
.DS_Store
node_modules
+src_bak
+src_bak/
node_modules/
server/
东北大学.com/
diff --git a/dist/css/app.387e87f6.css b/dist/css/app.387e87f6.css
new file mode 100644
index 0000000..62e159c
--- /dev/null
+++ b/dist/css/app.387e87f6.css
@@ -0,0 +1 @@
+.navbar[data-v-b2b9830c]{position:sticky;top:0;z-index:1000;width:100%;background:linear-gradient(90deg,#fff,#f8f9fa);box-shadow:0 2px 10px rgba(0,0,0,.05);height:64px}.navbar-container[data-v-b2b9830c]{max-width:1200px;margin:0 auto;padding:0 20px;height:100%;display:flex;align-items:center;justify-content:space-between}.navbar-brand[data-v-b2b9830c]{display:flex;align-items:center;cursor:pointer;transition:opacity .3s}.navbar-brand[data-v-b2b9830c]:hover{opacity:.8}.logo[data-v-b2b9830c]{height:40px;margin-right:12px}.brand-text[data-v-b2b9830c]{font-size:1.5rem;font-weight:700;color:#333;letter-spacing:.5px}.version-badge[data-v-b2b9830c]{background:linear-gradient(135deg,#225fc9,#5390e6);color:#fff;font-size:.75rem;padding:2px 8px;border-radius:12px;margin-left:10px;font-weight:700;box-shadow:0 2px 4px rgba(0,0,0,.2);position:relative;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;height:20px}.version-badge[data-v-b2b9830c]:after{content:"";position:absolute;top:0;left:-100%;width:100%;height:100%;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.4),transparent);transform:skewX(-20deg);animation:shine-b2b9830c 2s infinite}@keyframes shine-b2b9830c{0%{left:-100%}20%{left:200%}to{left:200%}}.navbar-menu[data-v-b2b9830c]{display:flex;gap:30px;align-items:center}.nav-item[data-v-b2b9830c]{text-decoration:none;color:#555;font-weight:500;font-size:16px;padding:8px 0;position:relative;transition:color .3s}.nav-item[data-v-b2b9830c]:hover{color:#409eff}.nav-item.active[data-v-b2b9830c]{color:#409eff;font-weight:600}.nav-item.active[data-v-b2b9830c]:after{content:"";position:absolute;bottom:0;left:0;width:100%;height:2px;background-color:#409eff;border-radius:2px}.navbar-toggle[data-v-b2b9830c]{background:none;border:none;cursor:pointer;padding:10px;display:none;margin-right:-10px}.hamburger-box[data-v-b2b9830c]{width:24px;height:24px;display:flex;align-items:center;justify-content:center;position:relative}.hamburger-inner[data-v-b2b9830c],.hamburger-inner[data-v-b2b9830c]:after,.hamburger-inner[data-v-b2b9830c]:before{width:24px;height:2px;background-color:#333;border-radius:2px;position:absolute;transition:transform .3s cubic-bezier(.4,.01,.165,.99),opacity .3s cubic-bezier(.4,.01,.165,.99),top .3s cubic-bezier(.4,.01,.165,.99),bottom .3s cubic-bezier(.4,.01,.165,.99);left:0}.hamburger-inner[data-v-b2b9830c]{top:50%;transform:translateY(-50%)}.hamburger-inner[data-v-b2b9830c]:before{content:"";top:-8px}.hamburger-inner[data-v-b2b9830c]:after{content:"";bottom:-8px}.hamburger-inner.is-active[data-v-b2b9830c]{transform:rotate(45deg)}.hamburger-inner.is-active[data-v-b2b9830c]:before{top:0;opacity:0}.hamburger-inner.is-active[data-v-b2b9830c]:after{bottom:0;transform:rotate(-90deg)}.mobile-menu-overlay[data-v-b2b9830c]{position:fixed;top:64px;left:0;width:100%;height:calc(100vh - 64px);background-color:rgba(0,0,0,.5);z-index:998}.mobile-menu-content[data-v-b2b9830c]{position:fixed;top:64px;left:0;right:0;background-color:#fff;z-index:999;box-shadow:0 4px 12px rgba(0,0,0,.1);padding:20px;display:flex;flex-direction:column;box-sizing:border-box}.mobile-menu-header[data-v-b2b9830c]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;border-bottom:1px solid #eee;padding-bottom:10px}.mobile-menu-title[data-v-b2b9830c]{font-size:1.2rem;font-weight:700;color:#333}.close-btn[data-v-b2b9830c]{font-size:2rem;line-height:1;cursor:pointer;color:#999}.mobile-links[data-v-b2b9830c]{display:flex;flex-direction:column;gap:15px}.mobile-nav-item[data-v-b2b9830c]{text-decoration:none;color:#333;font-size:1.1rem;padding:10px;border-radius:8px;background-color:#f9f9f9;text-align:center;transition:background-color .2s}.mobile-nav-item.active[data-v-b2b9830c]{background-color:#ecf5ff;color:#409eff;font-weight:600}.mobile-footer[data-v-b2b9830c]{margin-top:30px;text-align:center;color:#999;font-size:.8rem}@media (max-width:768px){.desktop-only[data-v-b2b9830c]{display:none}.mobile-only[data-v-b2b9830c]{display:block}.navbar-container[data-v-b2b9830c]{padding:0 15px}}.fade-enter-active[data-v-b2b9830c],.fade-leave-active[data-v-b2b9830c]{transition:opacity .3s}.fade-enter-from[data-v-b2b9830c],.fade-leave-to[data-v-b2b9830c]{opacity:0}.slide-down-enter-active[data-v-b2b9830c],.slide-down-leave-active[data-v-b2b9830c]{transition:transform .3s ease,opacity .3s}.slide-down-enter-from[data-v-b2b9830c],.slide-down-leave-to[data-v-b2b9830c]{transform:translateY(-20px);opacity:0}body,html{height:100%;margin:0;padding:0;background-color:#f5f7fa;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.app-layout{min-height:100vh;display:flex;flex-direction:column}.main-content{flex:1;padding:20px;width:100%;max-width:1200px;margin:0 auto;box-sizing:border-box}.forbidden-container{text-align:center;padding:50px 20px;display:flex;align-items:center;flex-direction:column;justify-content:center;min-height:100vh}.forbidden-title{color:#d9534f;font-size:2.5rem;margin-bottom:20px}.forbidden-text{font-size:1.25rem;color:#333;margin-bottom:30px;max-width:600px}.forbidden-back-btn{background-color:#5cb85c;color:#fff;padding:10px 20px;font-size:1.1rem;border:none;border-radius:5px;cursor:pointer;transition:background-color .3s ease}.forbidden-back-btn:hover{background-color:#4cae4c}@media (max-width:768px){.main-content{padding:15px}.forbidden-title{font-size:1.8rem}.forbidden-text{font-size:1rem}}h2[data-v-b5d4cca8]{color:#333;margin-bottom:10px;font-size:42px}@media (max-width:768px){h2[data-v-b5d4cca8]{font-size:28px}}p[data-v-b5d4cca8]{line-height:1.6;margin-bottom:15px;color:#666}.guide-link[data-v-b5d4cca8]{color:#0056b3;text-decoration:underline;cursor:pointer}.guide-link[data-v-b5d4cca8]:hover{color:#003d82}.course-list-page[data-v-2964ca48]{max-width:1200px;margin:0 auto;padding:20px;min-height:100vh;background-color:#f8f9fa}.page-title[data-v-2964ca48]{margin-bottom:20px;font-size:24px;color:#333;font-weight:700}.empty-message[data-v-2964ca48],.loading-message[data-v-2964ca48]{font-size:16px;color:#666;text-align:center;margin-top:40px}.course-cards[data-v-2964ca48]{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-bottom:40px}.course-card[data-v-2964ca48]{background:#fff;border-radius:12px;border:1px solid #f0f0f0;overflow:hidden;cursor:pointer;transition:all .3s ease;display:flex;flex-direction:column;height:100%;position:relative}.course-card[data-v-2964ca48]:hover{transform:translateY(-5px);box-shadow:0 8px 24px rgba(0,0,0,.08);border-color:#e0e0e0}.card-header[data-v-2964ca48]{padding:16px;border-bottom:1px solid #f9f9f9;display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.course-name-title[data-v-2964ca48]{font-size:16px;font-weight:600;color:#333;margin:0;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;flex:1}.status-tag[data-v-2964ca48]{font-size:12px;padding:2px 8px;border-radius:10px;white-space:nowrap;background:#eee;color:#666}.status-approved[data-v-2964ca48]{background:#e6f7ff;color:#1890ff;border:1px solid #91d5ff}.status-pending[data-v-2964ca48]{background:#fffbe6;color:#faad14;border:1px solid #ffe58f}.status-rejected[data-v-2964ca48]{background:#fff1f0;color:#f5222d;border:1px solid #ffa39e}.card-body[data-v-2964ca48]{padding:16px;flex:1}.info-row[data-v-2964ca48]{display:flex;justify-content:space-between;margin-bottom:8px;font-size:13px;color:#666}.info-label[data-v-2964ca48]{color:#999;margin-right:8px;flex-shrink:0}.info-val[data-v-2964ca48]{text-align:right;color:#333;font-weight:500}.truncate[data-v-2964ca48]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:70%}.card-footer[data-v-2964ca48]{padding:12px 16px;background:#fafafa;border-top:1px solid #f0f0f0}.time-info[data-v-2964ca48]{display:flex;flex-direction:column;gap:4px}.time-row[data-v-2964ca48]{display:flex;justify-content:space-between;font-size:12px;color:#999}.pagination-bar[data-v-2964ca48]{display:flex;justify-content:center;gap:8px;margin-bottom:40px;flex-wrap:wrap}.pagination-bar button[data-v-2964ca48]{min-width:36px;height:36px;padding:0 10px;border:1px solid #e0e0e0;background:#fff;color:#606266;border-radius:6px;cursor:pointer;transition:all .2s;font-size:14px}.pagination-bar button[data-v-2964ca48]:hover:not(:disabled){color:#409eff;border-color:#409eff}.pagination-bar button.active[data-v-2964ca48]{background-color:#409eff;border-color:#409eff;color:#fff}.pagination-bar button[data-v-2964ca48]:disabled{background:#f5f7fa;color:#c0c4cc;cursor:not-allowed}.add-course-section[data-v-2964ca48]{background:#fff;border-radius:12px;padding:24px;box-shadow:0 2px 12px rgba(0,0,0,.05);margin-top:40px}.section-header[data-v-2964ca48]{display:flex;align-items:center;gap:15px;margin-bottom:20px}.section-header h2[data-v-2964ca48]{margin:0;font-size:20px;color:#333}.help-btn[data-v-2964ca48]{display:flex;align-items:center;gap:5px;padding:5px 10px;background:#f8f9fa;border:1px solid #dee2e6;border-radius:4px;cursor:pointer;font-size:14px;color:#495057;transition:all .2s ease}.help-btn[data-v-2964ca48]:hover{background:#e9ecef}.help-icon[data-v-2964ca48]{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background:#6c757d;color:#fff;font-size:12px;font-weight:700}.input-grid[data-v-2964ca48]{display:grid;grid-template-columns:repeat(2,1fr);gap:30px}.input-group[data-v-2964ca48]{display:flex;flex-direction:column;gap:8px}.input-group label[data-v-2964ca48]{font-size:14px;color:#606266;font-weight:500}.modern-input[data-v-2964ca48],.modern-select[data-v-2964ca48]{width:100%;box-sizing:border-box;padding:10px;border:1px solid #e0e0e0;border-radius:8px;font-size:14px;transition:all .3s;background:#fff}.modern-input[data-v-2964ca48]:focus,.modern-select[data-v-2964ca48]:focus{border-color:#409eff;box-shadow:0 0 0 2px rgba(64,158,255,.2);outline:none}.button-group[data-v-2964ca48]{grid-column:1/-1;display:flex;justify-content:flex-end;margin-top:10px}.submit-btn[data-v-2964ca48]{padding:10px 30px;background-color:#409eff;color:#fff;border:none;border-radius:8px;font-weight:500;cursor:pointer;transition:all .3s}.submit-btn[data-v-2964ca48]:hover{background-color:#66b1ff;transform:translateY(-1px)}.help-modal[data-v-2964ca48]{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:1000}.help-modal-content[data-v-2964ca48]{background:#fff;border-radius:12px;width:90%;max-width:600px;max-height:80vh;overflow-y:auto;padding:20px;box-shadow:0 4px 6px rgba(0,0,0,.1)}.help-modal-header[data-v-2964ca48]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:10px;border-bottom:1px solid #dee2e6}.close-btn[data-v-2964ca48]{background:none;border:none;font-size:24px;cursor:pointer;color:#6c757d}.help-section[data-v-2964ca48]{margin-bottom:20px}.help-modal-header h3[data-v-2964ca48]{font-size:20px;font-weight:700;margin:0}.help-section h4[data-v-2964ca48]{color:#0056b3;margin-bottom:10px}.help-section p[data-v-2964ca48]{color:#495057;line-height:1.6;margin-bottom:8px}@media (max-width:768px){.course-cards[data-v-2964ca48]{grid-template-columns:repeat(2,1fr);gap:12px}.input-grid[data-v-2964ca48]{grid-template-columns:1fr}.course-name-title[data-v-2964ca48]{font-size:14px}.status-tag[data-v-2964ca48]{font-size:10px;padding:1px 5px}}@media (max-width:480px){.course-cards[data-v-2964ca48]{grid-template-columns:1fr}}.rating-page[data-v-39c1a23a]{max-width:1200px;margin:0 auto;padding:20px;background-color:#f8f9fa;min-height:100vh}.rating-note[data-v-39c1a23a]{font-size:14px;color:#666;margin-bottom:20px;text-align:center}.search-sort-bar[data-v-39c1a23a]{background:#fff;border-radius:12px;padding:20px;margin-bottom:30px;box-shadow:0 2px 12px rgba(0,0,0,.05);display:flex;flex-direction:column;gap:20px}.search-inputs[data-v-39c1a23a]{display:flex;gap:15px}.input-wrapper[data-v-39c1a23a]{position:relative;flex:1;display:flex;align-items:center}.search-icon[data-v-39c1a23a]{position:absolute;left:12px;color:#999;font-size:16px}.modern-input[data-v-39c1a23a]{width:100%;padding:10px 10px 10px 36px;border:1px solid #e0e0e0;border-radius:8px;font-size:14px;transition:all .3s}.modern-input[data-v-39c1a23a]:focus{border-color:#409eff;box-shadow:0 0 0 2px rgba(64,158,255,.2);outline:none}.teacher-input[data-v-39c1a23a]{flex:1.5}.filters-row[data-v-39c1a23a]{border-top:1px solid #f0f0f0;padding-top:15px}.category-checkboxes[data-v-39c1a23a]{display:flex;flex-wrap:wrap;gap:15px}.checkbox-label[data-v-39c1a23a]{display:flex;align-items:center;cursor:pointer;font-size:14px;color:#555;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:6px 12px;background:#f5f7fa;border-radius:20px;transition:all .2s}.checkbox-label[data-v-39c1a23a]:hover{background:#e6e8eb}.checkbox-label input[data-v-39c1a23a]{margin-right:6px}.actions-row[data-v-39c1a23a]{display:flex;justify-content:space-between;align-items:center;border-top:1px solid #f0f0f0;padding-top:15px}.select-group[data-v-39c1a23a]{display:flex;gap:15px}.modern-select[data-v-39c1a23a]{padding:8px 12px;border:1px solid #e0e0e0;border-radius:6px;font-size:14px;color:#555;background:#fff;cursor:pointer}.search-btn[data-v-39c1a23a]{padding:8px 24px;background-color:#409eff;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;transition:all .3s}.search-btn[data-v-39c1a23a]:hover{background-color:#66b1ff;transform:translateY(-1px)}.course-cards[data-v-39c1a23a]{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-bottom:30px}.course-card[data-v-39c1a23a]{background:#fff;border-radius:12px;border:1px solid #f0f0f0;overflow:hidden;cursor:pointer;transition:all .3s ease;display:flex;flex-direction:column;position:relative;height:100%}.course-card[data-v-39c1a23a]:hover{transform:translateY(-5px);box-shadow:0 8px 24px rgba(0,0,0,.08);border-color:#e0e0e0}.card-header[data-v-39c1a23a]{padding:16px;border-bottom:1px solid #f9f9f9}.course-name-title[data-v-39c1a23a]{font-size:16px;font-weight:600;color:#333;margin:0 0 8px 0;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;height:44px}.course-tags[data-v-39c1a23a]{display:flex;flex-wrap:wrap;gap:6px}.mini-tag[data-v-39c1a23a]{font-size:10px;padding:2px 6px;border:1px solid;border-radius:4px;white-space:nowrap}.card-body[data-v-39c1a23a]{padding:16px;flex:1}.info-row[data-v-39c1a23a]{display:flex;justify-content:space-between;margin-bottom:8px;font-size:13px;color:#666}.info-label[data-v-39c1a23a]{color:#999;margin-right:8px;flex-shrink:0}.info-val[data-v-39c1a23a]{text-align:right;color:#333;font-weight:500}.truncate[data-v-39c1a23a]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:70%}.card-footer[data-v-39c1a23a]{padding:12px 16px;background:#fafafa;border-top:1px solid #f0f0f0}.rating-info[data-v-39c1a23a]{display:flex;align-items:baseline;margin-bottom:8px}.score[data-v-39c1a23a]{font-size:24px;font-weight:700;color:#f90;line-height:1}.score-label[data-v-39c1a23a]{font-size:12px;color:#f90;margin-left:2px}.count[data-v-39c1a23a]{font-size:12px;color:#999;margin-left:auto}.top-comment[data-v-39c1a23a]{font-size:12px;color:#666;background:#fff;padding:8px;border-radius:6px;font-style:italic;line-height:1.4;border:1px solid #eee;height:50px;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.top-comment.placeholder[data-v-39c1a23a]{color:#ccc;font-style:normal;display:flex;align-items:center;justify-content:center}.pagination-bar[data-v-39c1a23a]{display:flex;justify-content:center;gap:8px;margin-top:30px}.pagination-bar button[data-v-39c1a23a]{min-width:36px;height:36px;padding:0 10px;border:1px solid #e0e0e0;background:#fff;color:#606266;border-radius:6px;cursor:pointer;transition:all .2s;font-size:14px}.pagination-bar button[data-v-39c1a23a]:hover:not(:disabled){color:#409eff;border-color:#409eff}.pagination-bar button.active[data-v-39c1a23a]{background-color:#409eff;border-color:#409eff;color:#fff}.pagination-bar button[data-v-39c1a23a]:disabled{background:#f5f7fa;color:#c0c4cc;cursor:not-allowed}@media (max-width:768px){.course-cards[data-v-39c1a23a]{grid-template-columns:repeat(2,1fr);gap:12px}.search-sort-bar[data-v-39c1a23a]{padding:15px}.search-inputs[data-v-39c1a23a]{flex-direction:column}.actions-row[data-v-39c1a23a]{flex-direction:column;gap:15px}.select-group[data-v-39c1a23a]{width:100%;flex-direction:column;gap:10px}.modern-select[data-v-39c1a23a]{width:100%}.pagination-bar[data-v-39c1a23a]{flex-wrap:wrap}.search-btn[data-v-39c1a23a]{width:100%}.course-name-title[data-v-39c1a23a]{font-size:14px;height:40px}.info-row[data-v-39c1a23a]{font-size:12px}.score[data-v-39c1a23a]{font-size:20px}}.rating-page[data-v-3228e625]{max-width:1200px;margin:0 auto;padding:20px;background-color:#f8f9fa;min-height:100vh}.rating-note[data-v-3228e625]{font-size:14px;color:#666;margin-bottom:20px;text-align:center}.search-sort-bar[data-v-3228e625]{background:#fff;border-radius:12px;padding:20px;margin-bottom:30px;box-shadow:0 2px 12px rgba(0,0,0,.05);display:flex;flex-direction:column;gap:20px}.search-inputs[data-v-3228e625]{display:flex;gap:15px}.input-wrapper[data-v-3228e625]{position:relative;flex:1;display:flex;align-items:center}.search-icon[data-v-3228e625]{position:absolute;left:12px;color:#999;font-size:16px}.modern-input[data-v-3228e625]{width:100%;padding:10px 10px 10px 36px;border:1px solid #e0e0e0;border-radius:8px;font-size:14px;transition:all .3s}.modern-input[data-v-3228e625]:focus{border-color:#409eff;box-shadow:0 0 0 2px rgba(64,158,255,.2);outline:none}.teacher-input[data-v-3228e625]{flex:1.5}.filters-row[data-v-3228e625]{border-top:1px solid #f0f0f0;padding-top:15px}.category-checkboxes[data-v-3228e625]{display:flex;flex-wrap:wrap;gap:15px}.checkbox-label[data-v-3228e625]{display:flex;align-items:center;cursor:pointer;font-size:14px;color:#555;-webkit-user-select:none;-moz-user-select:none;user-select:none;padding:6px 12px;background:#f5f7fa;border-radius:20px;transition:all .2s}.checkbox-label[data-v-3228e625]:hover{background:#e6e8eb}.checkbox-label input[data-v-3228e625]{margin-right:6px}.actions-row[data-v-3228e625]{display:flex;justify-content:space-between;align-items:center;border-top:1px solid #f0f0f0;padding-top:15px}.select-group[data-v-3228e625]{display:flex;gap:15px}.modern-select[data-v-3228e625]{padding:8px 12px;border:1px solid #e0e0e0;border-radius:6px;font-size:14px;color:#555;background:#fff;cursor:pointer}.search-btn[data-v-3228e625]{padding:8px 24px;background-color:#409eff;color:#fff;border:none;border-radius:6px;font-weight:500;cursor:pointer;transition:all .3s}.search-btn[data-v-3228e625]:hover{background-color:#66b1ff;transform:translateY(-1px)}.course-cards[data-v-3228e625]{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-bottom:30px}.course-card[data-v-3228e625]{background:#fff;border-radius:12px;border:1px solid #f0f0f0;overflow:hidden;cursor:pointer;transition:all .3s ease;display:flex;flex-direction:column;position:relative;height:100%}.course-card[data-v-3228e625]:hover{transform:translateY(-5px);box-shadow:0 8px 24px rgba(0,0,0,.08);border-color:#e0e0e0}.card-header[data-v-3228e625]{padding:16px;border-bottom:1px solid #f9f9f9}.course-name-title[data-v-3228e625]{font-size:16px;font-weight:600;color:#333;margin:0 0 8px 0;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;height:44px}.course-tags[data-v-3228e625]{display:flex;flex-wrap:wrap;gap:6px}.mini-tag[data-v-3228e625]{font-size:10px;padding:2px 6px;border:1px solid;border-radius:4px;white-space:nowrap}.card-body[data-v-3228e625]{padding:16px;flex:1}.info-row[data-v-3228e625]{display:flex;justify-content:space-between;margin-bottom:8px;font-size:13px;color:#666}.info-label[data-v-3228e625]{color:#999;margin-right:8px;flex-shrink:0}.info-val[data-v-3228e625]{text-align:right;color:#333;font-weight:500}.truncate[data-v-3228e625]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:70%}.card-footer[data-v-3228e625]{padding:12px 16px;background:#fafafa;border-top:1px solid #f0f0f0}.rating-info[data-v-3228e625]{display:flex;align-items:baseline;margin-bottom:8px}.score[data-v-3228e625]{font-size:24px;font-weight:700;color:#f90;line-height:1}.score-label[data-v-3228e625]{font-size:12px;color:#f90;margin-left:2px}.count[data-v-3228e625]{font-size:12px;color:#999;margin-left:auto}.top-comment[data-v-3228e625]{font-size:12px;color:#666;background:#fff;padding:8px;border-radius:6px;font-style:italic;line-height:1.4;border:1px solid #eee;height:50px;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.top-comment.placeholder[data-v-3228e625]{color:#ccc;font-style:normal;display:flex;align-items:center;justify-content:center}.pagination-bar[data-v-3228e625]{display:flex;justify-content:center;gap:8px;margin-top:30px}.pagination-bar button[data-v-3228e625]{min-width:36px;height:36px;padding:0 10px;border:1px solid #e0e0e0;background:#fff;color:#606266;border-radius:6px;cursor:pointer;transition:all .2s;font-size:14px}.pagination-bar button[data-v-3228e625]:hover:not(:disabled){color:#409eff;border-color:#409eff}.pagination-bar button.active[data-v-3228e625]{background-color:#409eff;border-color:#409eff;color:#fff}.pagination-bar button[data-v-3228e625]:disabled{background:#f5f7fa;color:#c0c4cc;cursor:not-allowed}@media (max-width:768px){.course-cards[data-v-3228e625]{grid-template-columns:repeat(2,1fr);gap:12px}.search-sort-bar[data-v-3228e625]{padding:15px}.search-inputs[data-v-3228e625]{flex-direction:column}.actions-row[data-v-3228e625]{flex-direction:column;gap:15px}.select-group[data-v-3228e625]{width:100%;flex-direction:column;gap:10px}.modern-select[data-v-3228e625]{width:100%}.pagination-bar[data-v-3228e625]{flex-wrap:wrap}.search-btn[data-v-3228e625]{width:100%}.course-name-title[data-v-3228e625]{font-size:14px;height:40px}.info-row[data-v-3228e625]{font-size:12px}.score[data-v-3228e625]{font-size:20px}}.modal-overlay[data-v-9c153036]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:999}.loading[data-v-9c153036]{display:flex;align-items:center;justify-content:center;flex-direction:column;text-align:center;height:200px}.el-icon[data-v-9c153036]{font-size:40px;margin-bottom:10px}.modal-content[data-v-9c153036]{background-color:#fff;padding:20px;border-radius:8px;width:80%;height:80%;display:flex;flex-direction:row;justify-content:space-between;position:relative}.close[data-v-9c153036]{position:absolute;top:10px;right:10px;cursor:pointer;font-size:24px}.course-detail[data-v-9c153036]{max-height:calc(90vh - 120px);overflow-y:auto;overflow-x:auto;padding-right:15px;width:40%}.course-detail[data-v-9c153036]::-webkit-scrollbar{width:6px;height:6px}.course-detail[data-v-9c153036]::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.course-detail[data-v-9c153036]::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.course-detail[data-v-9c153036]::-webkit-scrollbar-thumb:hover{background:#555}.course-detail[data-v-9c153036]>*{min-width:-moz-fit-content;min-width:fit-content}.rating-section[data-v-9c153036]{margin-top:20px}.total-rating[data-v-9c153036]{font-size:40px;margin-bottom:10px}.stars span[data-v-9c153036]{font-size:30px;cursor:pointer;transition:color .3s}.stars .highlighted[data-v-9c153036]{color:gold}.stars span[data-v-9c153036]:not(.highlighted){color:#ccc}.comment-section[data-v-9c153036]{width:55%;padding-left:20px}.comments-list[data-v-9c153036]{max-height:350px;overflow-y:auto;margin-bottom:20px}.comment[data-v-9c153036]{padding:10px 0;border-bottom:1px solid #ddd}.like-section[data-v-9c153036]{cursor:pointer;color:gray}.like-section.liked[data-v-9c153036]{color:red}.new-comment[data-v-9c153036]{display:flex;flex-direction:column}.new-comment input[data-v-9c153036],.new-comment textarea[data-v-9c153036]{margin-bottom:10px;padding:5px;border-radius:5px;border:1px solid #ccc}.new-comment button[data-v-9c153036]{padding:10px;background-color:#007bff;color:#fff;border:none;border-radius:5px;cursor:pointer}.comment-meta[data-v-9c153036],.comment-time[data-v-9c153036]{font-size:13px}.progress[data-v-9c153036]{margin-bottom:5px;width:250px}[data-v-9c153036] .progress .el-progress-bar__outer{height:20px!important;line-height:40px;background-color:#a19999}.course-title[data-v-9c153036]{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;border:1px solid;border-radius:12px;margin-left:4px;font-size:.85em;min-height:20px}.share-btn[data-v-9c153036]{background-color:#4caf50;color:#fff;border:none;padding:6px 12px;margin-left:10px;border-radius:4px;cursor:pointer;font-size:14px}.share-btn[data-v-9c153036]:hover{background-color:#45a049}.error-modal[data-v-9c153036],.share-modal[data-v-9c153036]{position:fixed;top:20%;left:50%;transform:translateX(-50%);color:#fff;padding:15px;border-radius:10px;text-align:center;box-shadow:0 4px 8px rgba(0,0,0,.1);font-size:16px;z-index:9999;animation:fadeInDown-9c153036 .5s ease}.share-modal[data-v-9c153036]{background-color:#4caf50}.error-modal[data-v-9c153036]{background-color:#f44}@keyframes fadeInDown-9c153036{0%{opacity:0;transform:translate(-50%,-30px)}to{opacity:1;transform:translate(-50%)}}.chat-start-btn[data-v-9c153036]{margin-left:10px;padding:5px 10px;background-color:#409eff;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .3s ease,transform .2s ease}.chat-start-btn[data-v-9c153036]:hover{background-color:#66b1ff;transform:scale(1.05)}.chat-start-btn[data-v-9c153036]:active{background-color:#3a8ee6;transform:scale(.95)}.chat-modal-overlay[data-v-9c153036]{position:fixed;top:0;left:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;z-index:1000;animation:chat-fadeIn-9c153036 .3s ease}.chat-modal-content[data-v-9c153036]{background:#fff;padding:20px;border-radius:8px;width:400px;box-shadow:0 2px 10px rgba(0,0,0,.1);text-align:center;animation:chat-slideIn-9c153036 .3s ease;position:relative}.chat-modal-content .chat-close-btn[data-v-9c153036]{position:absolute;top:10px;right:15px;font-size:20px;color:#999;cursor:pointer;transition:color .3s ease}.chat-modal-content .chat-close-btn[data-v-9c153036]:hover{color:#333}.chat-modal-content h3[data-v-9c153036]{margin-top:0;color:#333;font-size:18px}.chat-modal-actions[data-v-9c153036]{margin-top:20px;display:flex;justify-content:space-around}.chat-modal-actions button[data-v-9c153036]{padding:10px 20px;font-size:14px;border:none;border-radius:4px;cursor:pointer;transition:background-color .3s ease,transform .2s ease}.chat-modal-actions button[data-v-9c153036]:first-child{background-color:#409eff;color:#fff}.chat-modal-actions button[data-v-9c153036]:first-child:hover{background-color:#66b1ff}.chat-modal-actions button[data-v-9c153036]:first-child:active{background-color:#3a8ee6}.chat-modal-actions button[data-v-9c153036]:last-child{background-color:#f5f5f5;color:#666}.chat-modal-actions button[data-v-9c153036]:last-child:hover{background-color:#e0e0e0}.chat-modal-actions button[data-v-9c153036]:last-child:active{background-color:#d6d6d6}.chat-textarea[data-v-9c153036]{border:1px solid #dcdfe6;border-radius:4px;padding:10px;font-size:14px;width:100%;height:100px;box-sizing:border-box;resize:none;outline:none;transition:border-color .3s ease}.chat-textarea[data-v-9c153036]:focus{border-color:#409eff}@keyframes chat-fadeIn-9c153036{0%{opacity:0}to{opacity:1}}@keyframes chat-slideIn-9c153036{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}.delete-btn[data-v-9c153036]{color:red;background:none;border:none;cursor:pointer;margin-left:10px;font-size:14px;padding:2px 8px}.delete-btn[data-v-9c153036]:hover{text-decoration:underline}.comment-actions[data-v-9c153036]{display:flex;align-items:center;margin-top:10px;font-size:14px}.ai-summary[data-v-9c153036]{margin-top:15px;padding:10px;background-color:#f5f5f5;border-radius:4px;line-height:1.5}.typing-cursor[data-v-9c153036]{display:inline-block;width:6px;height:14px;background-color:#000;animation:blink-9c153036 1s step-start infinite;margin-left:2px;vertical-align:middle}@keyframes blink-9c153036{50%{opacity:0}}@media (max-width:768px){.modal-content[data-v-9c153036]{width:95%;height:95%;flex-direction:column;overflow-y:auto}.course-detail[data-v-9c153036]{width:100%;height:auto;max-height:none;border-right:none;border-bottom:1px solid #eee;padding-right:0;padding-bottom:20px;margin-bottom:20px}.comment-section[data-v-9c153036]{width:100%;padding-left:0}.total-rating[data-v-9c153036]{font-size:32px}.chat-modal-content[data-v-9c153036]{width:90%}}.chat-page[data-v-38851032]{display:flex;height:98vh;overflow:hidden}.sidebar[data-v-38851032]{width:300px;border-right:1px solid #ddd;display:flex;flex-direction:column;padding:10px;background-color:#f9f9f9}.sidebar h3[data-v-38851032]{margin-bottom:10px}.conversation-item[data-v-38851032]{padding:10px;margin:5px 0;border-radius:5px;cursor:pointer;background-color:#fff;transition:background-color .2s}.conversation-item[data-v-38851032]:hover{background-color:#f0f0f0}.conversation-item.active[data-v-38851032]{background-color:#e6f7ff;border-left:4px solid #1890ff}.conversation-name[data-v-38851032]{font-weight:700;display:flex;align-items:center}.role-label[data-v-38851032]{color:#fff;padding:2px 5px;border-radius:3px;margin-left:5px;font-size:12px}.role-label.owner[data-v-38851032]{background-color:#2196f3}.role-label.member[data-v-38851032]{background-color:#4caf50}.conversation-last-message[data-v-38851032],.conversation-updated-at[data-v-38851032]{color:#999;font-size:12px}.new-message-label[data-v-38851032]{background-color:red;color:#fff;padding:2px 5px;border-radius:3px;margin-left:5px;font-size:12px}.chat-container[data-v-38851032]{flex:1;display:flex;flex-direction:column;background-color:#f5f5f5;width:48.5vw;height:98vh;position:relative}.conversation-info[data-v-38851032]{padding:10px;background-color:#fff;border-bottom:1px solid #ddd;display:flex;justify-content:space-between;align-items:center}.message-list[data-v-38851032]{flex:1;padding:10px;overflow-y:auto}.message[data-v-38851032]{margin:10px 0;display:flex;flex-direction:column}.message.self[data-v-38851032]{align-items:flex-end}.message.other[data-v-38851032]{align-items:flex-start}.message-bubble[data-v-38851032]{max-width:60%;padding:10px;border-radius:8px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.1);position:relative}.message.self .message-bubble[data-v-38851032]{background-color:#daf1da}.message-info[data-v-38851032]{display:flex;margin-top:5px}.message-info.align-right[data-v-38851032]{justify-content:flex-end}.message-info.align-left[data-v-38851032]{justify-content:flex-start}.message-info small[data-v-38851032]{color:#999;font-size:12px;margin-left:5px}.input-container[data-v-38851032]{padding:10px;border-top:1px solid #ddd;text-align:center}.locked-input[data-v-38851032]{height:60px}.locked-input[data-v-38851032] .el-textarea__inner{resize:none!important}.header[data-v-38851032]{display:flex;justify-content:space-between;align-items:center}.connection-status[data-v-38851032]{display:flex;align-items:center;font-size:14px}.status-indicator[data-v-38851032]{width:8px;height:8px;border-radius:50%;margin-right:5px}.status-indicator.connected[data-v-38851032]{background-color:#02f23e}.status-indicator.disconnected[data-v-38851032]{background-color:#f44336}.status-text[data-v-38851032]{font-size:14px;font-weight:400}.connected .status-text[data-v-38851032]{color:#02f23e}.disconnected .status-text[data-v-38851032]{color:#f44336}.mobile-back-btn[data-v-38851032]{display:none;background:none;border:none;color:#007bff;font-size:16px;cursor:pointer;padding:0 10px 0 0;margin-right:10px}@media (max-width:768px){.chat-page[data-v-38851032]{height:calc(100vh - 64px)}.sidebar[data-v-38851032]{width:100%;border-right:none}.chat-container[data-v-38851032]{width:100%;height:100%;display:none}.chat-page.mobile-chat-active .sidebar[data-v-38851032]{display:none}.chat-page.mobile-chat-active .chat-container[data-v-38851032]{display:flex}.mobile-back-btn[data-v-38851032]{display:inline-block}.message-bubble[data-v-38851032]{max-width:80%}.conversation-info[data-v-38851032]{flex-wrap:wrap;gap:10px}}.about-container[data-v-5c1b02c2]{height:90vh;overflow:hidden;padding:20px}.about-page[data-v-5c1b02c2]{max-width:99%;margin:0 auto;height:100%;overflow-y:auto;padding-right:15px}.about-page[data-v-5c1b02c2]::-webkit-scrollbar{width:6px}.about-page[data-v-5c1b02c2]::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.about-page[data-v-5c1b02c2]::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.about-page[data-v-5c1b02c2]::-webkit-scrollbar-thumb:hover{background:#555}.project-intro[data-v-5c1b02c2]{margin-bottom:40px}h2[data-v-5c1b02c2]{color:#333;margin-bottom:20px;font-size:24px;border-bottom:2px solid #eee;padding-bottom:10px}.intro-content[data-v-5c1b02c2]{line-height:1.8;color:#666}.intro-content p[data-v-5c1b02c2]{margin-bottom:15px}.version-timeline[data-v-5c1b02c2]{margin-top:40px}.version-item[data-v-5c1b02c2]{background-color:#f8f9fa;padding:15px;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,.05);margin-bottom:10px}.version-item h4[data-v-5c1b02c2]{color:#409eff;margin:0 0 10px 0}.version-item p[data-v-5c1b02c2]{color:#666;margin:0}.version-item ul[data-v-5c1b02c2]{list-style-type:disc;margin:0;padding-left:20px}.version-item li[data-v-5c1b02c2]{margin-bottom:5px}[data-v-5c1b02c2] .el-timeline-item__node{background-color:#409eff}[data-v-5c1b02c2] .el-timeline-item__timestamp{color:#409eff;font-weight:700}@media (max-width:768px){.about-container[data-v-5c1b02c2]{height:auto;overflow:visible;padding:10px}.about-page[data-v-5c1b02c2]{overflow-y:visible;height:auto}}.course-detail-page[data-v-2c76732d]{background-color:#f5f7fa;min-height:100vh;padding-bottom:40px}.container[data-v-2c76732d]{max-width:1200px;margin:0 auto;padding:20px}.loading-state[data-v-2c76732d]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:60vh;color:#666}.spinner[data-v-2c76732d]{border:4px solid #f3f3f3;border-top:4px solid #409eff;border-radius:50%;width:40px;height:40px;animation:spin-2c76732d 1s linear infinite;margin-bottom:15px}@keyframes spin-2c76732d{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.card[data-v-2c76732d]{background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,.05);padding:24px;margin-bottom:24px;transition:all .3s ease}.card[data-v-2c76732d]:hover{box-shadow:0 4px 16px rgba(0,0,0,.08)}.top-section[data-v-2c76732d]{display:grid;grid-template-columns:1.2fr .8fr;gap:24px}.card-header[data-v-2c76732d]{margin-bottom:20px}.course-name[data-v-2c76732d]{font-size:24px;color:#333;margin:0;display:flex;align-items:center;flex-wrap:wrap;gap:10px}.tags[data-v-2c76732d]{display:flex;gap:8px}.tag[data-v-2c76732d]{font-size:12px;padding:2px 8px;border:1px solid;border-radius:12px;white-space:nowrap}.info-grid[data-v-2c76732d]{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}.info-item[data-v-2c76732d]{display:flex;flex-direction:column}.info-item.full-width[data-v-2c76732d]{grid-column:1/-1}.label[data-v-2c76732d]{font-size:13px;color:#909399;margin-bottom:4px}.value[data-v-2c76732d]{font-size:16px;color:#303133;font-weight:500}.share-btn[data-v-2c76732d]{background-color:#ecf5ff;color:#409eff;border:none;padding:10px 20px;border-radius:20px;cursor:pointer;font-weight:500;display:inline-flex;align-items:center;gap:6px;transition:background .2s}.share-btn[data-v-2c76732d]:hover{background-color:#d9ecff}.rating-overview[data-v-2c76732d]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px}.total-score[data-v-2c76732d]{display:flex;align-items:baseline;gap:8px}.score[data-v-2c76732d]{font-size:48px;font-weight:700;color:#409eff;line-height:1}.count[data-v-2c76732d]{color:#909399;font-size:14px}.user-rating-action p[data-v-2c76732d]{margin:0 0 5px 0;font-size:13px;color:#606266;text-align:center}.stars[data-v-2c76732d]{color:#ddd;font-size:24px;cursor:pointer}.stars.interactive span.active[data-v-2c76732d],.stars.interactive span[data-v-2c76732d]:hover{color:#f7ba2a}.bar-row[data-v-2c76732d]{display:flex;align-items:center;gap:10px;margin-bottom:8px;font-size:13px}.star-label[data-v-2c76732d]{width:30px;color:#606266}.el-progress[data-v-2c76732d]{flex:1}.percent[data-v-2c76732d]{width:35px;text-align:right;color:#909399}.section-header[data-v-2c76732d]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;border-bottom:1px solid #ebeef5;padding-bottom:15px}.section-header h2[data-v-2c76732d]{font-size:18px;margin:0;display:flex;align-items:center;gap:8px}.beta-badge[data-v-2c76732d]{background:#f56c6c;color:#fff;font-size:10px;padding:2px 6px;border-radius:4px;vertical-align:top}.ai-disclaimer[data-v-2c76732d]{font-size:12px;color:#909399}.ai-content[data-v-2c76732d]{line-height:1.6;color:#303133;min-height:80px}.cursor[data-v-2c76732d]{animation:blink-2c76732d 1s infinite}@keyframes blink-2c76732d{50%{opacity:0}}.sort-tabs[data-v-2c76732d]{display:flex;gap:10px;font-size:14px;color:#909399}.sort-tabs span[data-v-2c76732d]{cursor:pointer}.sort-tabs span.active[data-v-2c76732d]{color:#409eff;font-weight:700}.divider[data-v-2c76732d]{color:#ebeef5;cursor:default!important}.post-comment[data-v-2c76732d]{background:#f9fafc;padding:20px;border-radius:8px;margin-bottom:30px}.input-group[data-v-2c76732d]{display:flex;flex-direction:column;gap:10px;margin-bottom:10px}.nickname-input[data-v-2c76732d]{padding:8px 12px;border:1px solid #dcdfe6;border-radius:4px;width:200px}.comment-textarea[data-v-2c76732d]{padding:10px 12px;border:1px solid #dcdfe6;border-radius:4px;min-height:80px;resize:vertical}.submit-btn[data-v-2c76732d]{background:#409eff;color:#fff;border:none;padding:8px 24px;border-radius:4px;cursor:pointer;align-self:flex-end}.comment-item[data-v-2c76732d]{border-bottom:1px solid #ebeef5;padding:20px 0}.comment-item[data-v-2c76732d]:last-child{border-bottom:none}.comment-header[data-v-2c76732d]{display:flex;justify-content:space-between;margin-bottom:8px}.comment-author[data-v-2c76732d]{font-weight:700;color:#303133}.comment-date[data-v-2c76732d]{font-size:12px;color:#909399}.comment-body[data-v-2c76732d]{font-size:14px;color:#606266;margin-bottom:12px;white-space:pre-wrap}.comment-footer[data-v-2c76732d]{display:flex;justify-content:space-between;align-items:center;font-size:13px}.rating-tag span[data-v-2c76732d]{color:#f56c6c;font-weight:700}.actions[data-v-2c76732d]{display:flex;gap:15px}.like-btn[data-v-2c76732d]{cursor:pointer;color:#909399}.like-btn.liked[data-v-2c76732d]{color:#f56c6c}.action-link[data-v-2c76732d]{background:none;border:none;cursor:pointer;font-size:13px}.action-link.delete[data-v-2c76732d]{color:#f56c6c}.action-link.chat[data-v-2c76732d]{color:#409eff}.toast[data-v-2c76732d]{position:fixed;top:80px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.8);color:#fff;padding:10px 20px;border-radius:4px;z-index:2000}.modal-overlay[data-v-2c76732d]{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:2000}.modal-box[data-v-2c76732d]{background:#fff;width:90%;max-width:400px;padding:24px;border-radius:8px;position:relative}.close-btn[data-v-2c76732d]{position:absolute;right:15px;top:10px;font-size:24px;cursor:pointer;color:#909399}.modal-textarea[data-v-2c76732d]{width:90%;min-height:100px;margin:15px 0;padding:10px;border:1px solid #dcdfe6;border-radius:4px;resize:none}.modal-actions[data-v-2c76732d]{display:flex;justify-content:flex-end;gap:10px}.primary-btn[data-v-2c76732d]{background:#409eff;color:#fff;border:none;padding:8px 20px;border-radius:4px;cursor:pointer}.secondary-btn[data-v-2c76732d]{background:#fff;border:1px solid #dcdfe6;padding:8px 20px;border-radius:4px;cursor:pointer}@media (max-width:768px){.top-section[data-v-2c76732d]{grid-template-columns:1fr;gap:16px}.info-grid[data-v-2c76732d]{grid-template-columns:1fr}.rating-overview[data-v-2c76732d]{flex-direction:column;align-items:flex-start;gap:15px}.user-rating-action[data-v-2c76732d]{width:100%;display:flex;justify-content:space-between;align-items:center}.score[data-v-2c76732d]{font-size:36px}.nickname-input[data-v-2c76732d]{width:100%}}body{font-family:Microsoft YaHei,微软雅黑,Arial,sans-serif;margin:0;padding:0}*{font-family:inherit}
\ No newline at end of file
diff --git a/dist/css/app.4157a502.css b/dist/css/app.4157a502.css
deleted file mode 100644
index 29abe08..0000000
--- a/dist/css/app.4157a502.css
+++ /dev/null
@@ -1 +0,0 @@
-.el-menu-vertical-demo[data-v-fa32c4be]{border-right:none;display:flex;flex-direction:column;height:98%;width:250px}.el-menu-item[data-v-fa32c4be]{border-radius:8px}.el-menu-item[data-v-fa32c4be]:hover{background-color:#1d1e1f}.el-menu-item span[data-v-fa32c4be]{margin-left:10px}.sidebar-footer[data-v-fa32c4be]{margin-top:auto;padding:10px;text-align:center;font-size:14px;color:#888}.sidebar-footer a[data-v-fa32c4be]{color:#e0e4e8;text-decoration:none;bottom:20px;width:100%;text-align:center}.sidebar-footer a[data-v-fa32c4be]:hover{color:#9a9ea2;text-decoration:none}.footer-title[data-v-fa32c4be]{font-size:12px;color:#f6f0f0;text-align:center}.footer-info[data-v-fa32c4be]{margin-top:7px;font-size:12px;color:#beb5b5;text-align:center}.footer-info a[data-v-fa32c4be]{color:#beb5b5;text-decoration:none}.footer-info a[data-v-fa32c4be]:hover{color:#a8a4a6}body,html{height:100%;margin:0;padding:0}#app{display:flex;height:100vh}.sidebar{width:250px;background-color:#333;padding:10px;height:98%}.main-content{flex-grow:1;padding:20px;background-color:#fff;max-width:98%;max-height:98%}.forbidden-container{text-align:center;padding:50px;align-items:center;flex-direction:column;justify-content:center}.forbidden-title{color:#d9534f;font-size:2.5rem;margin-bottom:20px}.forbidden-text{font-size:1.25rem;color:#333;margin-bottom:30px}.forbidden-back-btn{background-color:#5cb85c;color:#fff;padding:10px 20px;font-size:1.1rem;border:none;border-radius:5px;cursor:pointer;transition:background-color .3s ease}.forbidden-back-btn:hover{background-color:#4cae4c}h2[data-v-b83355ba]{color:#333;margin-bottom:10px;font-size:42px}p[data-v-b83355ba]{line-height:1.6;margin-bottom:15px;color:#666}.guide-link[data-v-b83355ba]{color:#0056b3;text-decoration:underline;cursor:pointer}.guide-link[data-v-b83355ba]:hover{color:#003d82}.modal-overlay[data-v-5bb6a1dc]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:999}.loading[data-v-5bb6a1dc]{display:flex;align-items:center;justify-content:center;flex-direction:column;text-align:center;height:200px}.el-icon[data-v-5bb6a1dc]{font-size:40px;margin-bottom:10px}.modal-content[data-v-5bb6a1dc]{background-color:#fff;padding:20px;border-radius:8px;width:80%;height:80%;display:flex;flex-direction:row;justify-content:space-between;position:relative}.close[data-v-5bb6a1dc]{position:absolute;top:10px;right:10px;cursor:pointer;font-size:24px}.course-detail[data-v-5bb6a1dc]{max-height:calc(90vh - 120px);overflow-y:auto;overflow-x:auto;padding-right:15px;width:40%}.course-detail[data-v-5bb6a1dc]::-webkit-scrollbar{width:6px;height:6px}.course-detail[data-v-5bb6a1dc]::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.course-detail[data-v-5bb6a1dc]::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.course-detail[data-v-5bb6a1dc]::-webkit-scrollbar-thumb:hover{background:#555}.course-detail[data-v-5bb6a1dc]>*{min-width:-moz-fit-content;min-width:fit-content}.rating-section[data-v-5bb6a1dc]{margin-top:20px}.total-rating[data-v-5bb6a1dc]{font-size:40px;margin-bottom:10px}.stars span[data-v-5bb6a1dc]{font-size:30px;cursor:pointer;transition:color .3s}.stars .highlighted[data-v-5bb6a1dc]{color:gold}.stars span[data-v-5bb6a1dc]:not(.highlighted){color:#ccc}.comment-section[data-v-5bb6a1dc]{width:55%;padding-left:20px}.comments-list[data-v-5bb6a1dc]{max-height:350px;overflow-y:auto;margin-bottom:20px}.comment[data-v-5bb6a1dc]{padding:10px 0;border-bottom:1px solid #ddd}.like-section[data-v-5bb6a1dc]{cursor:pointer;color:gray}.like-section.liked[data-v-5bb6a1dc]{color:red}.new-comment[data-v-5bb6a1dc]{display:flex;flex-direction:column}.new-comment input[data-v-5bb6a1dc],.new-comment textarea[data-v-5bb6a1dc]{margin-bottom:10px;padding:5px;border-radius:5px;border:1px solid #ccc}.new-comment button[data-v-5bb6a1dc]{padding:10px;background-color:#007bff;color:#fff;border:none;border-radius:5px;cursor:pointer}.comment-meta[data-v-5bb6a1dc],.comment-time[data-v-5bb6a1dc]{font-size:13px}.progress[data-v-5bb6a1dc]{margin-bottom:5px;width:250px}[data-v-5bb6a1dc] .progress .el-progress-bar__outer{height:20px!important;line-height:40px;background-color:#a19999}.course-title[data-v-5bb6a1dc]{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;border:1px solid;border-radius:12px;margin-left:4px;font-size:.85em;min-height:20px}.share-btn[data-v-5bb6a1dc]{background-color:#4caf50;color:#fff;border:none;padding:6px 12px;margin-left:10px;border-radius:4px;cursor:pointer;font-size:14px}.share-btn[data-v-5bb6a1dc]:hover{background-color:#45a049}.error-modal[data-v-5bb6a1dc],.share-modal[data-v-5bb6a1dc]{position:fixed;top:20%;left:50%;transform:translateX(-50%);color:#fff;padding:15px;border-radius:10px;text-align:center;box-shadow:0 4px 8px rgba(0,0,0,.1);font-size:16px;z-index:9999;animation:fadeInDown-5bb6a1dc .5s ease}.share-modal[data-v-5bb6a1dc]{background-color:#4caf50}.error-modal[data-v-5bb6a1dc]{background-color:#f44}@keyframes fadeInDown-5bb6a1dc{0%{opacity:0;transform:translate(-50%,-30px)}to{opacity:1;transform:translate(-50%)}}.chat-start-btn[data-v-5bb6a1dc]{margin-left:10px;padding:5px 10px;background-color:#409eff;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .3s ease,transform .2s ease}.chat-start-btn[data-v-5bb6a1dc]:hover{background-color:#66b1ff;transform:scale(1.05)}.chat-start-btn[data-v-5bb6a1dc]:active{background-color:#3a8ee6;transform:scale(.95)}.chat-modal-overlay[data-v-5bb6a1dc]{position:fixed;top:0;left:0;right:0;bottom:0;display:flex;justify-content:center;align-items:center;z-index:1000;animation:chat-fadeIn-5bb6a1dc .3s ease}.chat-modal-content[data-v-5bb6a1dc]{background:#fff;padding:20px;border-radius:8px;width:400px;box-shadow:0 2px 10px rgba(0,0,0,.1);text-align:center;animation:chat-slideIn-5bb6a1dc .3s ease;position:relative}.chat-modal-content .chat-close-btn[data-v-5bb6a1dc]{position:absolute;top:10px;right:15px;font-size:20px;color:#999;cursor:pointer;transition:color .3s ease}.chat-modal-content .chat-close-btn[data-v-5bb6a1dc]:hover{color:#333}.chat-modal-content h3[data-v-5bb6a1dc]{margin-top:0;color:#333;font-size:18px}.chat-modal-actions[data-v-5bb6a1dc]{margin-top:20px;display:flex;justify-content:space-around}.chat-modal-actions button[data-v-5bb6a1dc]{padding:10px 20px;font-size:14px;border:none;border-radius:4px;cursor:pointer;transition:background-color .3s ease,transform .2s ease}.chat-modal-actions button[data-v-5bb6a1dc]:first-child{background-color:#409eff;color:#fff}.chat-modal-actions button[data-v-5bb6a1dc]:first-child:hover{background-color:#66b1ff}.chat-modal-actions button[data-v-5bb6a1dc]:first-child:active{background-color:#3a8ee6}.chat-modal-actions button[data-v-5bb6a1dc]:last-child{background-color:#f5f5f5;color:#666}.chat-modal-actions button[data-v-5bb6a1dc]:last-child:hover{background-color:#e0e0e0}.chat-modal-actions button[data-v-5bb6a1dc]:last-child:active{background-color:#d6d6d6}.chat-textarea[data-v-5bb6a1dc]{border:1px solid #dcdfe6;border-radius:4px;padding:10px;font-size:14px;width:100%;height:100px;box-sizing:border-box;resize:none;outline:none;transition:border-color .3s ease}.chat-textarea[data-v-5bb6a1dc]:focus{border-color:#409eff}@keyframes chat-fadeIn-5bb6a1dc{0%{opacity:0}to{opacity:1}}@keyframes chat-slideIn-5bb6a1dc{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}.delete-btn[data-v-5bb6a1dc]{color:red;background:none;border:none;cursor:pointer;margin-left:10px;font-size:14px;padding:2px 8px}.delete-btn[data-v-5bb6a1dc]:hover{text-decoration:underline}.comment-actions[data-v-5bb6a1dc]{display:flex;align-items:center;margin-top:10px;font-size:14px}.ai-summary[data-v-5bb6a1dc]{margin-top:15px;padding:10px;background-color:#f5f5f5;border-radius:4px;line-height:1.5}.typing-cursor[data-v-5bb6a1dc]{display:inline-block;animation:blink-5bb6a1dc .7s infinite;font-weight:700}@keyframes blink-5bb6a1dc{0%,to{opacity:1}50%{opacity:0}}.loading-message[data-v-72ba6bf4]{font-size:16px;color:#666;text-align:center;margin-top:20px}.course-table[data-v-72ba6bf4]{width:100%;border-collapse:collapse;max-height:270px;overflow-y:auto}.course-table thead[data-v-72ba6bf4]{position:sticky;top:0;z-index:1}.course-table td[data-v-72ba6bf4],.course-table th[data-v-72ba6bf4]{padding:10px;border-bottom:1px solid #ddd;text-align:left}.course-table th[data-v-72ba6bf4]{background-color:#f1f1f1;font-weight:700;box-shadow:0 2px 2px -1px rgba(0,0,0,.1)}.course-table tr[data-v-72ba6bf4]:hover{background-color:#f9f9f9}.input-section input[data-v-72ba6bf4],.input-section select[data-v-72ba6bf4]{display:block;margin:10px 0;padding:10px;width:100%;max-width:400px;border:1px solid #ccc;border-radius:4px;font-size:16px;transition:all .3s ease}.input-section input[data-v-72ba6bf4]:focus,.input-section select[data-v-72ba6bf4]:focus{border-color:#007bff;outline:none;box-shadow:0 0 8px rgba(0,123,255,.5)}.input-section button[data-v-72ba6bf4]{padding:10px 20px;background-color:#007bff;color:#fff;border:none;border-radius:8px;cursor:pointer;transition:transform .2s ease,background-color .3s ease}.input-section button[data-v-72ba6bf4]:hover{background-color:#0056b3;transform:scale(1.05)}.input-section button[data-v-72ba6bf4]:active{transform:scale(.95)}.pagination-bar[data-v-72ba6bf4]{margin-top:20px;text-align:center}.pagination-bar button[data-v-72ba6bf4]{margin:0 5px;padding:5px 10px;cursor:pointer;border:1px solid #ddd;border-radius:4px;background-color:#fff;transition:all .3s ease}.pagination-bar button[data-v-72ba6bf4]:hover{background-color:#0400f9;border-color:#0400f9;color:#fff}.pagination-bar .active[data-v-72ba6bf4]{background-color:#007bff;color:#fff;border-color:#007bff}.clickable-text[data-v-72ba6bf4]{color:#007bff;cursor:pointer;text-decoration:none;transition:color .2s ease}.clickable-text[data-v-72ba6bf4]:hover{color:#00008b}.clickable-text[data-v-72ba6bf4]:active{color:navy}.empty-message[data-v-72ba6bf4]{text-align:center;padding:20px;color:#666;font-size:16px}.section-header[data-v-72ba6bf4]{display:flex;align-items:center;gap:15px;margin-bottom:0}.help-btn[data-v-72ba6bf4]{display:flex;align-items:center;gap:5px;padding:5px 10px;background:#f8f9fa;border:1px solid #dee2e6;border-radius:4px;cursor:pointer;font-size:14px;color:#495057;transition:all .2s ease}.help-btn[data-v-72ba6bf4]:hover{background:#e9ecef}.help-icon[data-v-72ba6bf4]{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;background:#6c757d;color:#fff;font-size:12px;font-weight:700}.help-modal[data-v-72ba6bf4]{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:1000}.help-modal-content[data-v-72ba6bf4]{background:#fff;border-radius:12px;width:90%;max-width:600px;max-height:80vh;overflow-y:auto;padding:20px;box-shadow:0 4px 6px rgba(0,0,0,.1)}.help-modal-header[data-v-72ba6bf4]{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:10px;border-bottom:1px solid #dee2e6}.close-btn[data-v-72ba6bf4]{background:none;border:none;font-size:24px;cursor:pointer;color:#6c757d}.help-section[data-v-72ba6bf4]{margin-bottom:20px}.help-modal-header h3[data-v-72ba6bf4]{font-size:24px;font-weight:700;margin-bottom:4px}.help-section h4[data-v-72ba6bf4]{color:#0056b3;margin-bottom:10px}.help-section p[data-v-72ba6bf4]{color:#495057;line-height:1.6;margin-bottom:8px}.rating-page[data-v-7aa9d5ae]{padding:20px}.search-sort-bar[data-v-7aa9d5ae]{display:flex;flex-wrap:wrap;gap:15px;margin-bottom:20px;align-items:center}.search-sort-bar input[type=text][data-v-7aa9d5ae]{padding:8px 12px;font-size:16px;border:1px solid #ccc;border-radius:4px;width:200px}.search-sort-bar button[data-v-7aa9d5ae]{padding:8px 16px;background-color:#007bff;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:16px;transition:transform .2s ease}.search-sort-bar button[data-v-7aa9d5ae]:hover{background-color:#0056b3}.search-sort-bar button[data-v-7aa9d5ae]:active{transform:scale(.9)}.category-checkboxes label[data-v-7aa9d5ae]{display:flex;align-items:center;font-size:14px;cursor:pointer}.category-checkboxes input[type=checkbox][data-v-7aa9d5ae]{margin-right:6px;transform:scale(1.2);cursor:pointer}.search-sort-bar select[data-v-7aa9d5ae]{padding:8px 12px;font-size:16px;border:1px solid #ccc;border-radius:4px;cursor:pointer}.search-sort-bar select[data-v-7aa9d5ae]:focus{border-color:#007bff;outline:none}.category-checkboxes[data-v-7aa9d5ae]{display:flex;gap:10px}.course-cards[data-v-7aa9d5ae]{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-height:55vh;overflow-y:auto;overflow-x:hidden}.course-card[data-v-7aa9d5ae]{border:1px solid #ddd;padding:20px;border-radius:8px;cursor:pointer;transition:transform .3s;box-shadow:0 4px 8px rgba(29,28,28,.2);max-width:33vw}.course-card[data-v-7aa9d5ae]:hover{transform:scale(1.05)}.course-title[data-v-7aa9d5ae]{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;border:1px solid;border-radius:12px;margin-left:4px;font-size:.85em;min-height:20px}.pagination-bar[data-v-7aa9d5ae]{margin-top:20px;text-align:center}.pagination-bar button[data-v-7aa9d5ae]{margin:0 5px;padding:5px 10px;cursor:pointer;border:1px solid #ddd;border-radius:4px;background-color:#fff;transition:all .3s ease}.pagination-bar button[data-v-7aa9d5ae]:hover{background-color:#0400f9;border-color:#0400f9;color:#fff}.pagination-bar .active[data-v-7aa9d5ae]{background-color:#007bff;color:#fff;border-color:#007bff}.course-detail-modal[data-v-7aa9d5ae]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center}.modal-content[data-v-7aa9d5ae]{background-color:#fff;padding:20px;border-radius:8px;width:400px;position:relative}.modal-content .close[data-v-7aa9d5ae]{position:absolute;top:10px;right:10px;cursor:pointer;font-size:24px}.card-rate[data-v-7aa9d5ae]{font-size:22px;text-align:right;color:red}.unit[data-v-7aa9d5ae]{font-size:14px}.card-topcomment[data-v-7aa9d5ae]{font-size:15px}.card-college[data-v-7aa9d5ae],.card-ratecount[data-v-7aa9d5ae],.card-teachers[data-v-7aa9d5ae],.card-type[data-v-7aa9d5ae]{font-size:14px}.rating-note[data-v-7aa9d5ae]{font-size:18px}.select-container select[data-v-57f802ca]{display:inline-block}.sortBySelect[data-v-57f802ca]{margin-right:15px}.rating-page[data-v-57f802ca]{padding:20px}.search-sort-bar[data-v-57f802ca]{display:flex;flex-wrap:wrap;gap:15px;margin-bottom:20px;align-items:center}.search-sort-bar input[type=text][data-v-57f802ca]{padding:8px 12px;font-size:16px;border:1px solid #ccc;border-radius:4px;width:200px}.search-sort-bar button[data-v-57f802ca]{padding:8px 16px;background-color:#007bff;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:16px;transition:transform .2s ease}.search-sort-bar button[data-v-57f802ca]:hover{background-color:#0056b3}.search-sort-bar button[data-v-57f802ca]:active{transform:scale(.9)}.category-checkboxes label[data-v-57f802ca]{display:flex;align-items:center;font-size:14px;cursor:pointer}.category-checkboxes input[type=checkbox][data-v-57f802ca]{margin-right:6px;transform:scale(1.2);cursor:pointer}.search-sort-bar select[data-v-57f802ca]{padding:8px 12px;font-size:16px;border:1px solid #ccc;border-radius:4px;cursor:pointer}.search-sort-bar select[data-v-57f802ca]:focus{border-color:#007bff;outline:none}.category-checkboxes[data-v-57f802ca]{display:flex;gap:10px}.course-cards[data-v-57f802ca]{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-height:55vh;overflow-y:auto;overflow-x:hidden}.course-card[data-v-57f802ca]{border:1px solid #ddd;padding:20px;border-radius:8px;cursor:pointer;transition:transform .3s;box-shadow:0 4px 8px rgba(29,28,28,.2);max-width:33vw}.course-card[data-v-57f802ca]:hover{transform:scale(1.05)}.course-title[data-v-57f802ca]{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;border:1px solid;border-radius:12px;margin-left:4px;font-size:.85em;min-height:20px}.pagination-bar[data-v-57f802ca]{margin-top:20px;text-align:center}.pagination-bar button[data-v-57f802ca]{margin:0 5px;padding:5px 10px;cursor:pointer;border:1px solid #ddd;border-radius:4px;background-color:#fff;transition:all .3s ease}.pagination-bar button[data-v-57f802ca]:hover{background-color:#0400f9;border-color:#0400f9;color:#fff}.pagination-bar .active[data-v-57f802ca]{background-color:#007bff;color:#fff;border-color:#007bff}.course-detail-modal[data-v-57f802ca]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center}.modal-content[data-v-57f802ca]{background-color:#fff;padding:20px;border-radius:8px;width:400px;position:relative}.modal-content .close[data-v-57f802ca]{position:absolute;top:10px;right:10px;cursor:pointer;font-size:24px}.card-rate[data-v-57f802ca]{font-size:22px;text-align:right;color:red}.unit[data-v-57f802ca]{font-size:14px}.card-topcomment[data-v-57f802ca]{font-size:15px}.card-college[data-v-57f802ca],.card-ratecount[data-v-57f802ca],.card-teachers[data-v-57f802ca],.card-type[data-v-57f802ca]{font-size:14px}.rating-note[data-v-57f802ca]{font-size:18px}.chat-page[data-v-6c274ce6]{display:flex;height:98vh;overflow:hidden}.sidebar[data-v-6c274ce6]{width:300px;border-right:1px solid #ddd;display:flex;flex-direction:column;padding:10px;background-color:#f9f9f9}.sidebar h3[data-v-6c274ce6]{margin-bottom:10px}.conversation-item[data-v-6c274ce6]{padding:10px;margin:5px 0;border-radius:5px;cursor:pointer;background-color:#fff;transition:background-color .2s}.conversation-item[data-v-6c274ce6]:hover{background-color:#f0f0f0}.conversation-item.active[data-v-6c274ce6]{background-color:#e6f7ff;border-left:4px solid #1890ff}.conversation-name[data-v-6c274ce6]{font-weight:700;display:flex;align-items:center}.role-label[data-v-6c274ce6]{color:#fff;padding:2px 5px;border-radius:3px;margin-left:5px;font-size:12px}.role-label.owner[data-v-6c274ce6]{background-color:#2196f3}.role-label.member[data-v-6c274ce6]{background-color:#4caf50}.conversation-last-message[data-v-6c274ce6],.conversation-updated-at[data-v-6c274ce6]{color:#999;font-size:12px}.new-message-label[data-v-6c274ce6]{background-color:red;color:#fff;padding:2px 5px;border-radius:3px;margin-left:5px;font-size:12px}.chat-container[data-v-6c274ce6]{flex:1;display:flex;flex-direction:column;background-color:#f5f5f5;width:48.5vw;height:98vh;position:relative}.conversation-info[data-v-6c274ce6]{padding:10px;background-color:#fff;border-bottom:1px solid #ddd;display:flex;justify-content:space-between;align-items:center}.message-list[data-v-6c274ce6]{flex:1;padding:10px;overflow-y:auto}.message[data-v-6c274ce6]{margin:10px 0;display:flex;flex-direction:column}.message.self[data-v-6c274ce6]{align-items:flex-end}.message.other[data-v-6c274ce6]{align-items:flex-start}.message-bubble[data-v-6c274ce6]{max-width:60%;padding:10px;border-radius:8px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.1);position:relative}.message.self .message-bubble[data-v-6c274ce6]{background-color:#daf1da}.message-info[data-v-6c274ce6]{display:flex;margin-top:5px}.message-info.align-right[data-v-6c274ce6]{justify-content:flex-end}.message-info.align-left[data-v-6c274ce6]{justify-content:flex-start}.message-info small[data-v-6c274ce6]{color:#999;font-size:12px;margin-left:5px}.input-container[data-v-6c274ce6]{padding:10px;border-top:1px solid #ddd;text-align:center}.locked-input[data-v-6c274ce6]{height:60px}.locked-input[data-v-6c274ce6] .el-textarea__inner{resize:none!important}.header[data-v-6c274ce6]{display:flex;justify-content:space-between;align-items:center}.connection-status[data-v-6c274ce6]{display:flex;align-items:center;font-size:14px}.status-indicator[data-v-6c274ce6]{width:8px;height:8px;border-radius:50%;margin-right:5px}.status-indicator.connected[data-v-6c274ce6]{background-color:#02f23e}.status-indicator.disconnected[data-v-6c274ce6]{background-color:#f44336}.status-text[data-v-6c274ce6]{font-size:14px;font-weight:400}.connected .status-text[data-v-6c274ce6]{color:#02f23e}.disconnected .status-text[data-v-6c274ce6]{color:#f44336}.about-container[data-v-310fde40]{height:90vh;overflow:hidden;padding:20px}.about-page[data-v-310fde40]{max-width:99%;margin:0 auto;height:100%;overflow-y:auto;padding-right:15px}.about-page[data-v-310fde40]::-webkit-scrollbar{width:6px}.about-page[data-v-310fde40]::-webkit-scrollbar-track{background:#f1f1f1;border-radius:3px}.about-page[data-v-310fde40]::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.about-page[data-v-310fde40]::-webkit-scrollbar-thumb:hover{background:#555}.project-intro[data-v-310fde40]{margin-bottom:40px}h2[data-v-310fde40]{color:#333;margin-bottom:20px;font-size:24px;border-bottom:2px solid #eee;padding-bottom:10px}.intro-content[data-v-310fde40]{line-height:1.8;color:#666}.intro-content p[data-v-310fde40]{margin-bottom:15px}.version-timeline[data-v-310fde40]{margin-top:40px}.version-item[data-v-310fde40]{background-color:#f8f9fa;padding:15px;border-radius:8px;box-shadow:0 2px 4px rgba(0,0,0,.05);margin-bottom:10px}.version-item h4[data-v-310fde40]{color:#409eff;margin:0 0 10px 0}.version-item p[data-v-310fde40]{color:#666;margin:0}.version-item ul[data-v-310fde40]{list-style-type:disc;margin:0;padding-left:20px}.version-item li[data-v-310fde40]{margin-bottom:5px}[data-v-310fde40] .el-timeline-item__node{background-color:#409eff}[data-v-310fde40] .el-timeline-item__timestamp{color:#409eff;font-weight:700}body{font-family:Microsoft YaHei,微软雅黑,Arial,sans-serif;margin:0;padding:0}*{font-family:inherit}
\ No newline at end of file
diff --git a/dist/index.html b/dist/index.html
index fa5e553..da3fc75 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -1 +1 @@
-
NEU小站课程评分系统 本系统需要JavaScript支持,请启用JavaScript后继续。
\ No newline at end of file
+NEU小站课程评分系统 本系统需要JavaScript支持,请启用JavaScript后继续。
\ No newline at end of file
diff --git a/dist/js/app.2c83ed37.js b/dist/js/app.2c83ed37.js
new file mode 100644
index 0000000..9e36acf
--- /dev/null
+++ b/dist/js/app.2c83ed37.js
@@ -0,0 +1,2 @@
+(function(){"use strict";var e={4707:function(e,t,s){var a=s(5130),o=s(6768);const n={key:0,class:"app-layout"},i={class:"main-content"},r={key:1,class:"forbidden-container"};function c(e,t,s,a,c,l){const u=(0,o.g2)("NavBar"),d=(0,o.g2)("router-view");return(0,o.uX)(),(0,o.CE)("div",null,[c.isAuthorized?((0,o.uX)(),(0,o.CE)("div",n,[(0,o.bF)(u),(0,o.Lk)("main",i,[(0,o.bF)(d)])])):((0,o.uX)(),(0,o.CE)("div",r,t[0]||(t[0]=[(0,o.Fv)('您的访问被拒绝 只有在 NEU小站 完成 校园网或校园邮箱验证 的用户才能访问课程评分系统。
请确保您已完成相关操作,然后重新尝试访问。
返回登录页面 ',4)])))])}s(4114);var l=s(4232);const u={class:"navbar"},d={class:"navbar-container"},h={class:"navbar-menu desktop-only"},m={class:"hamburger-box"},p={key:0,class:"mobile-menu-content"},g={class:"mobile-links"};function k(e,t,s,n,i,r){const c=(0,o.g2)("router-link");return(0,o.uX)(),(0,o.CE)("nav",u,[(0,o.Lk)("div",d,[(0,o.Lk)("div",{class:"navbar-brand",onClick:t[0]||(t[0]=t=>e.$router.push("/"))},t[3]||(t[3]=[(0,o.Lk)("img",{src:"https://download.xn--xhq44jb2fzpc.com/images/logo-hd.png",alt:"NEU小站",class:"logo"},null,-1),(0,o.Lk)("span",{class:"brand-text"},"课程评分",-1),(0,o.Lk)("span",{class:"version-badge"},"V2",-1)])),(0,o.Lk)("div",h,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.menuItems,(e=>((0,o.uX)(),(0,o.Wv)(c,{key:e.name,to:e.path,class:"nav-item","active-class":"active"},{default:(0,o.k6)((()=>[(0,o.eW)((0,l.v_)(e.label),1)])),_:2},1032,["to"])))),128))]),(0,o.Lk)("button",{class:"navbar-toggle mobile-only",onClick:t[1]||(t[1]=(...e)=>r.toggleMenu&&r.toggleMenu(...e)),"aria-label":"Toggle navigation"},[(0,o.Lk)("span",m,[(0,o.Lk)("span",{class:(0,l.C4)(["hamburger-inner",{"is-active":i.isMenuOpen}])},null,2)])])]),(0,o.bF)(a.eB,{name:"fade"},{default:(0,o.k6)((()=>[i.isMenuOpen?((0,o.uX)(),(0,o.CE)("div",{key:0,class:"mobile-menu-overlay",onClick:t[2]||(t[2]=(...e)=>r.closeMenu&&r.closeMenu(...e))})):(0,o.Q3)("",!0)])),_:1}),(0,o.bF)(a.eB,{name:"slide-down"},{default:(0,o.k6)((()=>[i.isMenuOpen?((0,o.uX)(),(0,o.CE)("div",p,[t[4]||(t[4]=(0,o.Lk)("div",{class:"mobile-menu-header"},[(0,o.Lk)("span",{class:"mobile-menu-title"},"菜单")],-1)),(0,o.Lk)("div",g,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.menuItems,(e=>((0,o.uX)(),(0,o.Wv)(c,{key:e.name,to:e.path,class:"mobile-nav-item","active-class":"active",onClick:r.closeMenu},{default:(0,o.k6)((()=>[(0,o.eW)((0,l.v_)(e.label),1)])),_:2},1032,["to","onClick"])))),128))]),t[5]||(t[5]=(0,o.Lk)("div",{class:"mobile-footer"}," © 2025 NEU小站 ",-1))])):(0,o.Q3)("",!0)])),_:1})])}var v={name:"NavBar",data(){return{isMenuOpen:!1,menuItems:[{label:"使用必看",path:"/",name:"home"},{label:"选修课评分",path:"/rating",name:"rating"},{label:"必修课评分",path:"/ratingforcomp",name:"ratingforcomp"},{label:"我的课程",path:"/courses",name:"course-list"},{label:"关于",path:"/about",name:"about"}]}},methods:{toggleMenu(){this.isMenuOpen=!this.isMenuOpen},closeMenu(){this.isMenuOpen=!1}}},C=s(1241);const b=(0,C.A)(v,[["render",k],["__scopeId","data-v-b2b9830c"]]);var y=b,f={name:"App",data(){return{isAuthorized:!1,authChecked:!1}},components:{NavBar:y},mounted(){this.checkLoginStatus()},methods:{async checkLoginStatus(){const e=document.cookie.split("; ").reduce(((e,t)=>{const[s,a]=t.split("=");return s&&a&&(e[s.trim()]=decodeURIComponent(a)),e}),{}).token;if(e)try{const t=await fetch("https://newfront.xn--xhq44jb2fzpc.com/user/info",{method:"GET",headers:{Authorization:e}}),s=await t.json();t.ok&&!0===s.activated?this.isAuthorized=!0:console.warn("用户未通过验证:用户未激活")}catch(t){console.error("获取用户信息失败:",t)}finally{this.authChecked=!0}}}};const L=(0,C.A)(f,[["render",c]]);var w=L,_=s(6762),S=(s(4188),s(973));const E={key:0},x={id:"homepage-title"},P={key:1};function M(e,t,s,a,n,i){const r=(0,o.g2)("router-link");return n.isLoaded?((0,o.uX)(),(0,o.CE)("div",E,[(0,o.Lk)("div",null,[(0,o.Lk)("h2",x,(0,l.v_)(n.greeting)+", "+(0,l.v_)(n.nickname)+"!",1),t[9]||(t[9]=(0,o.Fv)("欢迎您使用NEU小站课程评分系统!
本系统采用全匿名方式 ,学生可以匿名对课程进行评分和发表评论。每人对每个课程只能评分一次,若需要多次评分,系统将记录用户最后一次提交的评分结果。为保护隐私,发表评论时不会显示用户在NEU小站的用户名,每次评论的昵称均由用户自行定义。
本系统中,课程分为两大类:选修课和必修课。 选修课有8个小类:通识选修、人文选修、专业方向、体育、学科基础、暑期国际课、数学与自然科学、重修专栏。人文选修类包括采用“抢选”方式进行选课的所有选修课,以及“改革开放史”和“社会主义发展史”两门人文社会科学类的选修课。 体育课单独作为一类,不属于人文选修类。重修课程的选课归为选修课的“重修专栏”类别,不属于必修课范畴。 重修专栏可以分享任何类别课程 ,但仅限分享重修体验 。
必修课有5个小类:数学与自然科学、人文社会科学、学科基础、专业方向、实践。如上所述,本系统中重修的必修课程也属于选修课范畴。 特别说明:军训课程属于实践类,系辅导员给分,在创建课程时课程教师请填写辅导员。
",4)),(0,o.Lk)("p",null,[t[1]||(t[1]=(0,o.eW)(" 在创建课程时,请先了解课程的类别,以及课程的")),t[2]||(t[2]=(0,o.Lk)("strong",null,"开课院系",-1)),t[3]||(t[3]=(0,o.eW)(",")),(0,o.bF)(r,{to:"/courses?m=true",class:"guide-link"},{default:(0,o.k6)((()=>t[0]||(t[0]=[(0,o.eW)("点击此处")]))),_:1}),t[4]||(t[4]=(0,o.eW)("查看指引。")),t[5]||(t[5]=(0,o.Lk)("strong",null,'如果同一课程的任课教师不同,用户可以创建多个同名课程,例如"A老师-篮球"和"B老师-篮球"将被视为两个不同的课程。',-1)),t[6]||(t[6]=(0,o.eW)("创建的课程卡片")),t[7]||(t[7]=(0,o.Lk)("strong",null,"需经过管理员审核",-1)),t[8]||(t[8]=(0,o.eW)(',审核进度可在"我的课程"中实时查看。 '))]),t[10]||(t[10]=(0,o.Lk)("p",null,[(0,o.eW)(" 本系统鼓励同学们提供真实、有价值的评分。"),(0,o.Lk)("strong",null,"禁止发布带有侮辱性的人身攻击等恶意评论。"),(0,o.eW)("管理员将对恶意用户进行封禁处理,确保评分系统的文明环境。 ")],-1))])])):((0,o.uX)(),(0,o.CE)("div",P,t[11]||(t[11]=[(0,o.Lk)("p",null,"加载中,请稍后...",-1)])))}var T={data(){return{name:"Homepage",greeting:"",nickname:"",isLoaded:!1}},mounted(){this.setGreeting(),this.fetchNickname(),setTimeout((()=>{this.isLoaded=!0}),300)},methods:{setGreeting(){const e=(new Date).getHours();this.greeting=e<12?"早上好":e<14?"中午好":e<18?"下午好":"晚上好"},async fetchNickname(){const e=document.cookie.split("; ").reduce(((e,t)=>{const[s,a]=t.split("=");return e[s]=decodeURIComponent(a),e}),{}).token;if(e)try{const t=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/avatar/nickname",{method:"GET",headers:{Authorization:e}});if(!t.ok){const e=await t.json();return void console.error("获取昵称失败:",e.message||"未知错误")}const s=await t.json();s.nickname?(this.nickname=s.nickname,console.log("Nickname successfully fetched:",s.nickname)):(this.nickname="默认昵称",console.log("Nickname field is missing. Using default nickname."))}catch(t){console.error("获取昵称时出错:",t)}else console.error("未找到JWT信息")}}};const I=(0,C.A)(T,[["render",M],["__scopeId","data-v-b5d4cca8"]]);var X=I;const j={class:"course-list-page"},$={key:0,class:"loading-message"},F={key:1,class:"empty-message"},A={key:2,class:"course-cards"},z=["onClick"],N={class:"card-header"},W={class:"course-name-title"},U={class:"card-body"},O={class:"info-row"},V={class:"info-val"},R={class:"info-row"},D={class:"info-val truncate"},q={class:"info-row"},B={class:"info-val truncate"},Q={class:"card-footer"},J={class:"time-info"},K={class:"time-row"},H={class:"time-val"},G={class:"time-row"},Y={class:"time-val"},Z={key:3,class:"pagination-bar"},ee=["disabled"],te=["onClick"],se=["disabled"],ae={class:"add-course-section card-style"},oe={class:"section-header"},ne={class:"input-grid"},ie={class:"input-group"},re={class:"input-group"},ce={class:"input-group"},le=["value"],ue={class:"input-group"},de={class:"button-group"},he={key:4,class:"help-modal"},me={class:"help-modal-content"},pe={class:"help-modal-header"};function ge(e,t,s,n,i,r){return(0,o.uX)(),(0,o.CE)("div",j,[t[24]||(t[24]=(0,o.Lk)("h2",{class:"page-title"},"我添加的课程",-1)),i.isLoaded?0===i.submissions.length?((0,o.uX)(),(0,o.CE)("div",F," 您还没有添加任何课程。 ")):((0,o.uX)(),(0,o.CE)("div",A,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.paginatedSubmissions,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.submit_id,class:"course-card",onClick:t=>r.handleCardClick(e)},[(0,o.Lk)("div",N,[(0,o.Lk)("h3",W,(0,l.v_)(e.course_name),1),(0,o.Lk)("div",{class:(0,l.C4)(["status-tag",r.getStatusClass(e.status)])},(0,l.v_)(e.status),3)]),(0,o.Lk)("div",U,[(0,o.Lk)("div",O,[t[9]||(t[9]=(0,o.Lk)("span",{class:"info-label"},"分类",-1)),(0,o.Lk)("span",V,(0,l.v_)(r.getCategoryName(e.category_id)),1)]),(0,o.Lk)("div",R,[t[10]||(t[10]=(0,o.Lk)("span",{class:"info-label"},"教师",-1)),(0,o.Lk)("span",D,(0,l.v_)(e.teachers),1)]),(0,o.Lk)("div",q,[t[11]||(t[11]=(0,o.Lk)("span",{class:"info-label"},"院系",-1)),(0,o.Lk)("span",B,(0,l.v_)(r.getCollegeName(e.college)),1)])]),(0,o.Lk)("div",Q,[(0,o.Lk)("div",J,[(0,o.Lk)("div",K,[t[12]||(t[12]=(0,o.Lk)("span",{class:"time-label"},"提交:",-1)),(0,o.Lk)("span",H,(0,l.v_)(r.formatTimeShort(e.create_time)),1)]),(0,o.Lk)("div",G,[t[13]||(t[13]=(0,o.Lk)("span",{class:"time-label"},"更新:",-1)),(0,o.Lk)("span",Y,(0,l.v_)(r.formatTimeShort(e.status_update_time)),1)])])])],8,z)))),128))])):((0,o.uX)(),(0,o.CE)("div",$," 加载中,请稍后... ")),i.totalPages>1?((0,o.uX)(),(0,o.CE)("div",Z,[(0,o.Lk)("button",{onClick:t[0]||(t[0]=e=>r.goToPage(1)),class:(0,l.C4)({active:1===i.currentPage}),disabled:1===i.currentPage},"首页",10,ee),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.getPaginationPages(),(e=>((0,o.uX)(),(0,o.CE)("button",{key:e,onClick:t=>r.goToPage(e),class:(0,l.C4)({active:i.currentPage===e})},(0,l.v_)(e),11,te)))),128)),(0,o.Lk)("button",{onClick:t[1]||(t[1]=e=>r.goToPage(i.totalPages)),class:(0,l.C4)({active:i.currentPage===i.totalPages}),disabled:i.currentPage===i.totalPages}," 尾页 ",10,se)])):(0,o.Q3)("",!0),(0,o.Lk)("div",ae,[(0,o.Lk)("div",oe,[t[15]||(t[15]=(0,o.Lk)("h2",null,"我要添加课程",-1)),(0,o.Lk)("button",{class:"help-btn",onClick:t[2]||(t[2]=e=>i.showHelp=!0)},t[14]||(t[14]=[(0,o.Lk)("span",{class:"help-icon"},"?",-1),(0,o.eW)(" 帮助 ")]))]),(0,o.Lk)("div",ne,[(0,o.Lk)("div",ie,[t[16]||(t[16]=(0,o.Lk)("label",null,"课程名称",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[3]||(t[3]=e=>i.newCourseName=e),type:"text",placeholder:"请输入课程名称",class:"modern-input"},null,512),[[a.Jo,i.newCourseName]])]),(0,o.Lk)("div",re,[t[18]||(t[18]=(0,o.Lk)("label",null,"课程类别",-1)),(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[4]||(t[4]=e=>i.newCategoryId=e),class:"modern-select"},t[17]||(t[17]=[(0,o.Fv)('请选择课程类别 选修课-通识选修类 选修课-人文选修类 选修课-专业方向类 选修课-体育类 选修课-学科基础类 选修课-暑期国际课 选修课-数学与自然科学类 选修课-重修专栏 必修课-数学与自然科学类 必修课-人文社会科学类 必修课-学科基础类 必修课-专业方向类 必修课-实践类 ',14)]),512),[[a.u1,i.newCategoryId]])]),(0,o.Lk)("div",ce,[t[20]||(t[20]=(0,o.Lk)("label",null,"开课院系",-1)),(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[5]||(t[5]=e=>i.newCollege=e),class:"modern-select"},[t[19]||(t[19]=(0,o.Lk)("option",{value:"",disabled:""},"请选择开课院系",-1)),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.filteredColleges,((e,t)=>((0,o.uX)(),(0,o.CE)("option",{key:t,value:t},(0,l.v_)(e),9,le)))),128))],512),[[a.u1,i.newCollege]])]),(0,o.Lk)("div",ue,[t[21]||(t[21]=(0,o.Lk)("label",null,"任课教师",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[6]||(t[6]=e=>i.newTeachers=e),type:"text",placeholder:"多个教师用英文逗号隔开,如A,B",class:"modern-input"},null,512),[[a.Jo,i.newTeachers]])]),(0,o.Lk)("div",de,[(0,o.Lk)("button",{onClick:t[7]||(t[7]=(...e)=>r.submitCourse&&r.submitCourse(...e)),class:"submit-btn"},"提交课程")])])]),i.showHelp?((0,o.uX)(),(0,o.CE)("div",he,[(0,o.Lk)("div",me,[(0,o.Lk)("div",pe,[t[22]||(t[22]=(0,o.Lk)("h3",null,"关于本系统课程信息的说明",-1)),(0,o.Lk)("button",{class:"close-btn",onClick:t[8]||(t[8]=e=>i.showHelp=!1)},"×")]),t[23]||(t[23]=(0,o.Fv)('一些说明 本系统中,课程分为两大类:选修课和必修课。 选修课有8个小类:通识选修、人文选修、专业方向、体育、学科基础、暑期国际课、数学与自然科学、重修专栏。人文选修类包括采用“抢选”方式进行选课的所有选修课,以及“改革开放史”和“社会主义发展史”两门人文社会科学类的选修课。 体育课单独作为一类,不属于人文选修类。重修课程的选课归为选修课的“重修专栏”类别,不属于必修课范畴。 重修专栏可以分享任何类别课程 ,但仅限分享重修体验 。
必修课有5个小类:数学与自然科学、人文社会科学、学科基础、专业方向、实践。如上所述,本系统中重修的必修课程也属于选修课范畴。 特别说明:军训课程属于实践类,系辅导员给分,在创建课程时课程教师请填写辅导员。
在创建课程时,请先了解课程的类别,以及课程的开课院系(详见下文) 。如果同一课程的任课教师不同,用户可以创建多个同名课程,例如“A老师-篮球”和“B老师-篮球”将被视为两个不同的课程。 创建的课程卡片需经过管理员审核 ,审核进度可在“我的课程”中实时查看。
如何查看课程类别和开课院系? 1. 本人课程 在教务系统选择“我的考试”,选择对应的学期后,即可查看当前学期的课程类别和开课院系。
2. 非本人课程 在教务系统选择“公共课表查询”,课表类型选择“班级课表”,再选好要查询的学期,并填写要查询的班级名称,点击查询按钮。
进入班级课表后,即可对应课程的开课院系。然后记下老师的姓名。
然后回到公共课表查询页面,课表类型选择“教师课表”,同样选好要查询的学期,并填写要查询的教师姓名,点击查询按钮。
进入教师课表后,找到此课程,即可查看课程类别。
',1))])])):(0,o.Q3)("",!0)])}s(4979);var ke={components:{},data(){return{submissions:[],newCourseName:"",newCategoryId:"",newTeachers:"",newCollege:"",currentPage:1,itemsPerPage:10,totalPages:1,isLoaded:!1,cachedEmail:null,showHelp:!1,maxVisiblePages:10,collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"}}},computed:{paginatedSubmissions(){const e=(this.currentPage-1)*this.itemsPerPage,t=e+this.itemsPerPage;return this.submissions.slice(e,t)},filteredColleges(){return Object.fromEntries(Object.entries(this.collegeMap).filter((([e])=>"59"!==e)))}},mounted(){this.checkMobile(),window.addEventListener("resize",this.checkMobile),setTimeout((async()=>{this.isLoaded=!0,this.fetchSubmissions()}),300),"true"===this.$route.query.m&&(this.showHelp=!0);const e=this.$route.query.c;if(e)try{const t=atob(e);this.isPositiveInteger(t)&&this.$router.push(`/detail/${t}`)}catch(t){}},beforeUnmount(){window.removeEventListener("resize",this.checkMobile)},methods:{checkMobile(){this.maxVisiblePages=window.innerWidth<=768?5:10},isPositiveInteger(e){const t=Number(e);return Number.isInteger(t)&&t>0},async fetchSubmissions(){const e=this.getCookie("token");if(e)try{const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/user/user-submissions",{method:"GET",headers:{"Content-Type":"application/json",Authorization:e}});if(200!==t.status){const e=await t.json();return void alert(e.error||"查询投稿记录失败")}const s=await t.json();this.submissions=s,this.totalPages=Math.ceil(this.submissions.length/this.itemsPerPage)}catch(t){console.error("Fetch submissions error",t)}},getCookie(e){const t=document.cookie.split(";");for(let s of t){const[t,a]=s.trim().split("=");if(t===e)return a}return null},goToPage(e){e<1||e>this.totalPages||(this.currentPage=e)},getPaginationPages(){const e=[],t=this.totalPages,s=this.currentPage,a=this.maxVisiblePages;if(t<=a)for(let o=1;o<=t;o++)e.push(o);else{let o=s-Math.floor(a/2);o=Math.max(o,1);let n=o+a-1;n>t&&(n=t,o=Math.max(n-a+1,1));for(let t=o;t<=n;t++)e.push(t)}return e},async submitCourse(){if(this.newCourseName&&this.newCategoryId&&this.newTeachers&&this.newCollege){if(confirm("确认提交审核吗?")){const e=this.getCookie("token");if(!e)return void alert("无法获取JWT,请重新登录。");const t={course_name:this.newCourseName,category_id:this.newCategoryId,teachers:this.newTeachers,college:this.newCollege};await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/user/submit-course",{method:"POST",headers:{"Content-Type":"application/json",Authorization:e},body:JSON.stringify(t)}),this.newCourseName="",this.newCategoryId="",this.newTeachers="",this.newCollege="",this.fetchSubmissions()}}else alert("请填写所有字段后提交!")},getCategoryName(e){const t={1:"通识选修类",2:"人文选修类",3:"专业方向类",4:"体育类",5:"学科基础类",6:"暑期国际课",7:"数学与自然科学类",8:"重修专栏",9:"必修-数理",10:"必修-人文",11:"必修-学科",12:"必修-专业",13:"必修-实践"};return t[e]||"未知分类"},formatTime(e){const t=new Date(e),s=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0"),n=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${s}-${a}-${o} ${n}:${i}`},formatTimeShort(e){if(!e)return"-";const t=new Date(e),s=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0");return`${s}-${a}`},handleCardClick(e){0!==e.course_id&&this.$router.push(`/detail/${e.course_id}`)},getStatusClass(e){return"已通过"===e?"status-approved":"待审核"===e?"status-pending":"已拒绝"===e?"status-rejected":""},getCollegeName(e){return this.collegeMap[e]||"未知院系"}}};const ve=(0,C.A)(ke,[["render",ge],["__scopeId","data-v-2964ca48"]]);var Ce=ve;const be={key:0,class:"rating-page"},ye={class:"search-sort-bar card-style"},fe={class:"search-inputs"},Le={class:"input-wrapper"},we={class:"input-wrapper teacher-input"},_e={class:"filters-row"},Se={class:"category-checkboxes"},Ee=["value"],xe={class:"actions-row"},Pe={class:"select-group"},Me=["value"],Te={class:"course-cards"},Ie=["onClick"],Xe={class:"card-header"},je={class:"course-name-title"},$e={key:0,class:"course-tags"},Fe={class:"card-body"},Ae={class:"info-row"},ze={class:"info-val"},Ne={class:"info-row"},We={class:"info-val truncate"},Ue={class:"info-row"},Oe={class:"info-val truncate"},Ve={class:"card-footer"},Re={class:"rating-info"},De={class:"score"},qe={class:"count"},Be={key:0,class:"top-comment"},Qe={key:1,class:"top-comment placeholder"},Je={class:"pagination-bar"},Ke=["onClick"],He=["disabled"],Ge={key:1};function Ye(e,t,s,n,i,r){return i.isLoaded?((0,o.uX)(),(0,o.CE)("div",be,[t[17]||(t[17]=(0,o.Lk)("h2",{class:"rating-note"},"每页最多展示12个课程,一次最多展示10个页码。点击星星进行评分,星星记录的是您的历史评分。",-1)),(0,o.Lk)("div",ye,[(0,o.Lk)("div",fe,[(0,o.Lk)("div",Le,[t[8]||(t[8]=(0,o.Lk)("span",{class:"search-icon"},"🔍",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[0]||(t[0]=e=>i.searchQuery=e),type:"text",placeholder:"搜索课程...",class:"modern-input"},null,512),[[a.Jo,i.searchQuery]])]),(0,o.Lk)("div",we,[t[9]||(t[9]=(0,o.Lk)("span",{class:"search-icon"},"👨🏫",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[1]||(t[1]=e=>i.teacherQuery=e),type:"text",placeholder:"搜索教师 (如: 张三,李四)",class:"modern-input"},null,512),[[a.Jo,i.teacherQuery]])])]),(0,o.Lk)("div",_e,[(0,o.Lk)("div",Se,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.categories,(e=>((0,o.uX)(),(0,o.CE)("label",{key:e.value,class:"checkbox-label"},[(0,o.bo)((0,o.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[2]||(t[2]=e=>i.selectedCategories=e),value:e.value},null,8,Ee),[[a.lH,i.selectedCategories]]),t[10]||(t[10]=(0,o.Lk)("span",{class:"checkmark"},null,-1)),(0,o.eW)(" "+(0,l.v_)(e.label),1)])))),128))])]),(0,o.Lk)("div",xe,[(0,o.Lk)("div",Pe,[(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[3]||(t[3]=e=>i.sortBy=e),class:"modern-select"},t[11]||(t[11]=[(0,o.Lk)("option",{value:"rating"},"评分由高到低",-1),(0,o.Lk)("option",{value:"rating-asc"},"评分由低到高",-1),(0,o.Lk)("option",{value:"rating_count"},"评分人数由多到少",-1)]),512),[[a.u1,i.sortBy]]),(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[4]||(t[4]=e=>i.selectedCollege=e),class:"modern-select"},[t[12]||(t[12]=(0,o.Lk)("option",{value:""},"全部院系",-1)),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.filteredColleges,(([e,t])=>((0,o.uX)(),(0,o.CE)("option",{key:e,value:e},(0,l.v_)(t),9,Me)))),128))],512),[[a.u1,i.selectedCollege]])]),(0,o.Lk)("button",{onClick:t[5]||(t[5]=(...e)=>r.searchCourses&&r.searchCourses(...e)),class:"search-btn"}," 更新查询 ")])]),(0,o.Lk)("div",Te,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.courses,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.course_id,class:"course-card",onClick:t=>r.showCourseDetail(e)},[(0,o.Lk)("div",Xe,[(0,o.Lk)("h3",je,(0,l.v_)(e.course_name),1),e.titles&&e.titles.length>0?((0,o.uX)(),(0,o.CE)("div",$e,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(e.titles,(e=>((0,o.uX)(),(0,o.CE)("span",{key:e.title,class:"mini-tag",style:(0,l.Tr)({borderColor:e.color,color:e.color})},(0,l.v_)(e.title),5)))),128))])):(0,o.Q3)("",!0)]),(0,o.Lk)("div",Fe,[(0,o.Lk)("div",Ae,[t[13]||(t[13]=(0,o.Lk)("span",{class:"info-label"},"分类",-1)),(0,o.Lk)("span",ze,(0,l.v_)(r.getCategoryName(e.category_id)),1)]),(0,o.Lk)("div",Ne,[t[14]||(t[14]=(0,o.Lk)("span",{class:"info-label"},"教师",-1)),(0,o.Lk)("span",We,(0,l.v_)(e.teachers),1)]),(0,o.Lk)("div",Ue,[t[15]||(t[15]=(0,o.Lk)("span",{class:"info-label"},"院系",-1)),(0,o.Lk)("span",Oe,(0,l.v_)(r.getCollegeName(e.college)),1)])]),(0,o.Lk)("div",Ve,[(0,o.Lk)("div",Re,[(0,o.Lk)("span",De,(0,l.v_)(e.rating),1),t[16]||(t[16]=(0,o.Lk)("span",{class:"score-label"},"分",-1)),(0,o.Lk)("span",qe,"("+(0,l.v_)(e.rating_count)+"人)",1)]),e.top_comment?((0,o.uX)(),(0,o.CE)("div",Be,' "'+(0,l.v_)(r.formatTopComment(e.top_comment))+'" ',1)):((0,o.uX)(),(0,o.CE)("div",Qe," 暂无评论 "))])],8,Ie)))),128))]),(0,o.Lk)("div",Je,[(0,o.Lk)("button",{onClick:t[6]||(t[6]=e=>r.goToPage(1)),class:(0,l.C4)({active:1===i.currentPage})},"首页",2),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.getPaginationPages(),(e=>((0,o.uX)(),(0,o.CE)("button",{key:e,onClick:t=>r.goToPage(e),class:(0,l.C4)({active:i.currentPage===e})},(0,l.v_)(e),11,Ke)))),128)),(0,o.Lk)("button",{onClick:t[7]||(t[7]=e=>r.goToPage(i.totalPages)),class:(0,l.C4)({active:i.currentPage===i.totalPages}),disabled:0===i.totalPages}," 尾页 ",10,He)])])):((0,o.uX)(),(0,o.CE)("div",Ge,t[18]||(t[18]=[(0,o.Lk)("p",{style:{color:"#666"}},"加载中,请稍后...",-1)])))}var Ze={data(){return{searchQuery:"",teacherQuery:"",sortBy:"rating",sortOrder:"desc",selectedCategories:[],courses:[],currentPage:1,totalPages:1,courseComments:[],isLoaded:!1,selectedCollege:"",allColleges:[],categories:[{label:"通识选修类",value:"1"},{label:"人文选修类",value:"2"},{label:"专业方向类",value:"3"},{label:"体育类",value:"4"},{label:"学科基础类",value:"5"},{label:"暑期国际课",value:"6"},{label:"数学与自然科学类",value:"7"},{label:"重修专栏",value:"8"}],maxVisiblePages:10,collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"}}},computed:{filteredColleges(){return Object.entries(this.collegeMap).filter((([e])=>"59"!==e))}},mounted(){this.checkMobile(),window.addEventListener("resize",this.checkMobile),setTimeout((()=>{this.isLoaded=!0,this.searchCourses()}),300),this.allColleges=Object.keys(this.collegeMap).map(Number)},beforeUnmount(){window.removeEventListener("resize",this.checkMobile)},methods:{checkMobile(){this.maxVisiblePages=window.innerWidth<=768?5:10},async fetchCourses(){let e="rating-asc"===this.sortBy?"rating":this.sortBy;this.sortOrder="rating-asc"===this.sortBy?"asc":"desc";const t=0===this.selectedCategories.length?"1,2,3,4,5,6,7,8":this.selectedCategories.join(","),s=this.selectedCollege?`&college=${this.selectedCollege}`:"",a=encodeURIComponent(this.searchQuery),o=encodeURIComponent(this.teacherQuery),n=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/list/courses?search=${a}&teacher=${o}&sortBy=${e}&sort=${this.sortOrder}&category=${t}${s}&page=${this.currentPage}`),i=await n.json();this.courses=i.courses,this.currentPage=i.currentPage,this.totalPages=i.totalPages},getPaginationPages(){const e=[],t=this.totalPages,s=this.currentPage,a=this.maxVisiblePages;if(t<=a)for(let o=1;o<=t;o++)e.push(o);else{let o=s-Math.floor(a/2);o=Math.max(o,1);let n=o+a-1;n>t&&(n=t,o=Math.max(n-a+1,1));for(let t=o;t<=n;t++)e.push(t)}return e},searchCourses(){this.currentPage=1,this.fetchCourses()},goToPage(e){e<1||e>this.totalPages||(this.currentPage=e,this.fetchCourses())},showCourseDetail(e){this.$router.push(`/detail/${e.course_id}`)},formatTopComment(e){if(!e)return"";let t=0,s="";for(let a=0;a255?1:.5;if(t+o>29)return s+"...";t+=o,s+=e[a]}return s},getCategoryName(e){const t={1:"通识选修类",2:"人文选修类",3:"专业方向类",4:"体育类",5:"学科基础类",6:"暑期国际课",7:"数学与自然科学类",8:"重修专栏"};return t[e]||"未知分类"},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"}}};const et=(0,C.A)(Ze,[["render",Ye],["__scopeId","data-v-39c1a23a"]]);var tt=et;const st={key:0,class:"rating-page"},at={class:"search-sort-bar card-style"},ot={class:"search-inputs"},nt={class:"input-wrapper"},it={class:"input-wrapper teacher-input"},rt={class:"filters-row"},ct={class:"category-checkboxes"},lt=["value"],ut={class:"actions-row"},dt={class:"select-group"},ht=["value"],mt={class:"course-cards"},pt=["onClick"],gt={class:"card-header"},kt={class:"course-name-title"},vt={key:0,class:"course-tags"},Ct={class:"card-body"},bt={class:"info-row"},yt={class:"info-val"},ft={class:"info-row"},Lt={class:"info-val truncate"},wt={class:"info-row"},_t={class:"info-val truncate"},St={class:"card-footer"},Et={class:"rating-info"},xt={class:"score"},Pt={class:"count"},Mt={key:0,class:"top-comment"},Tt={key:1,class:"top-comment placeholder"},It={class:"pagination-bar"},Xt=["onClick"],jt=["disabled"],$t={key:1};function Ft(e,t,s,n,i,r){return i.isLoaded?((0,o.uX)(),(0,o.CE)("div",st,[t[17]||(t[17]=(0,o.Lk)("h2",{class:"rating-note"},"每页最多展示12个课程,一次最多展示10个页码。点击星星进行评分,星星记录的是您的历史评分。",-1)),(0,o.Lk)("div",at,[(0,o.Lk)("div",ot,[(0,o.Lk)("div",nt,[t[8]||(t[8]=(0,o.Lk)("span",{class:"search-icon"},"🔍",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[0]||(t[0]=e=>i.searchQuery=e),type:"text",placeholder:"搜索课程...",class:"modern-input"},null,512),[[a.Jo,i.searchQuery]])]),(0,o.Lk)("div",it,[t[9]||(t[9]=(0,o.Lk)("span",{class:"search-icon"},"👨🏫",-1)),(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[1]||(t[1]=e=>i.teacherQuery=e),type:"text",placeholder:"搜索教师 (如: 张三,李四)",class:"modern-input"},null,512),[[a.Jo,i.teacherQuery]])])]),(0,o.Lk)("div",rt,[(0,o.Lk)("div",ct,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.categories,(e=>((0,o.uX)(),(0,o.CE)("label",{key:e.value,class:"checkbox-label"},[(0,o.bo)((0,o.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[2]||(t[2]=e=>i.selectedCategories=e),value:e.value},null,8,lt),[[a.lH,i.selectedCategories]]),t[10]||(t[10]=(0,o.Lk)("span",{class:"checkmark"},null,-1)),(0,o.eW)(" "+(0,l.v_)(e.label),1)])))),128))])]),(0,o.Lk)("div",ut,[(0,o.Lk)("div",dt,[(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[3]||(t[3]=e=>i.sortBy=e),class:"modern-select"},t[11]||(t[11]=[(0,o.Lk)("option",{value:"rating"},"评分由高到低",-1),(0,o.Lk)("option",{value:"rating-asc"},"评分由低到高",-1),(0,o.Lk)("option",{value:"rating_count"},"评分人数由多到少",-1)]),512),[[a.u1,i.sortBy]]),(0,o.bo)((0,o.Lk)("select",{"onUpdate:modelValue":t[4]||(t[4]=e=>i.selectedCollege=e),class:"modern-select"},[t[12]||(t[12]=(0,o.Lk)("option",{value:""},"全部院系",-1)),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.filteredColleges,(([e,t])=>((0,o.uX)(),(0,o.CE)("option",{key:e,value:e},(0,l.v_)(t),9,ht)))),128))],512),[[a.u1,i.selectedCollege]])]),(0,o.Lk)("button",{onClick:t[5]||(t[5]=(...e)=>r.searchCourses&&r.searchCourses(...e)),class:"search-btn"}," 更新查询 ")])]),(0,o.Lk)("div",mt,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.courses,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.course_id,class:"course-card",onClick:t=>r.showCourseDetail(e)},[(0,o.Lk)("div",gt,[(0,o.Lk)("h3",kt,(0,l.v_)(e.course_name),1),e.titles&&e.titles.length>0?((0,o.uX)(),(0,o.CE)("div",vt,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(e.titles,(e=>((0,o.uX)(),(0,o.CE)("span",{key:e.title,class:"mini-tag",style:(0,l.Tr)({borderColor:e.color,color:e.color})},(0,l.v_)(e.title),5)))),128))])):(0,o.Q3)("",!0)]),(0,o.Lk)("div",Ct,[(0,o.Lk)("div",bt,[t[13]||(t[13]=(0,o.Lk)("span",{class:"info-label"},"分类",-1)),(0,o.Lk)("span",yt,(0,l.v_)(r.getCategoryName(e.category_id)),1)]),(0,o.Lk)("div",ft,[t[14]||(t[14]=(0,o.Lk)("span",{class:"info-label"},"教师",-1)),(0,o.Lk)("span",Lt,(0,l.v_)(e.teachers),1)]),(0,o.Lk)("div",wt,[t[15]||(t[15]=(0,o.Lk)("span",{class:"info-label"},"院系",-1)),(0,o.Lk)("span",_t,(0,l.v_)(r.getCollegeName(e.college)),1)])]),(0,o.Lk)("div",St,[(0,o.Lk)("div",Et,[(0,o.Lk)("span",xt,(0,l.v_)(e.rating),1),t[16]||(t[16]=(0,o.Lk)("span",{class:"score-label"},"分",-1)),(0,o.Lk)("span",Pt,"("+(0,l.v_)(e.rating_count)+"人)",1)]),e.top_comment?((0,o.uX)(),(0,o.CE)("div",Mt,' "'+(0,l.v_)(r.formatTopComment(e.top_comment))+'" ',1)):((0,o.uX)(),(0,o.CE)("div",Tt," 暂无评论 "))])],8,pt)))),128))]),(0,o.Lk)("div",It,[(0,o.Lk)("button",{onClick:t[6]||(t[6]=e=>r.goToPage(1)),class:(0,l.C4)({active:1===i.currentPage})},"首页",2),((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(r.getPaginationPages(),(e=>((0,o.uX)(),(0,o.CE)("button",{key:e,onClick:t=>r.goToPage(e),class:(0,l.C4)({active:i.currentPage===e})},(0,l.v_)(e),11,Xt)))),128)),(0,o.Lk)("button",{onClick:t[7]||(t[7]=e=>r.goToPage(i.totalPages)),class:(0,l.C4)({active:i.currentPage===i.totalPages}),disabled:0===i.totalPages}," 尾页 ",10,jt)])])):((0,o.uX)(),(0,o.CE)("div",$t,t[18]||(t[18]=[(0,o.Lk)("p",{style:{color:"#666"}},"加载中,请稍后...",-1)])))}var At={data(){return{searchQuery:"",teacherQuery:"",sortBy:"rating",sortOrder:"desc",selectedCategories:[],courses:[],currentPage:1,totalPages:1,courseComments:[],isLoaded:!1,selectedCollege:"",allColleges:[],categories:[{label:"数学与自然科学类",value:"9"},{label:"人文社会科学类",value:"10"},{label:"学科基础类",value:"11"},{label:"专业方向类",value:"12"},{label:"实践类",value:"13"}],maxVisiblePages:10,collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"}}},computed:{filteredColleges(){return Object.entries(this.collegeMap).filter((([e])=>"59"!==e))}},mounted(){this.checkMobile(),window.addEventListener("resize",this.checkMobile),setTimeout((()=>{this.isLoaded=!0,this.searchCourses()}),300),this.allColleges=Object.keys(this.collegeMap).map(Number)},beforeUnmount(){window.removeEventListener("resize",this.checkMobile)},methods:{checkMobile(){this.maxVisiblePages=window.innerWidth<=768?5:10},async fetchCourses(){let e="rating-asc"===this.sortBy?"rating":this.sortBy;this.sortOrder="rating-asc"===this.sortBy?"asc":"desc";const t=0===this.selectedCategories.length?"9,10,11,12,13":this.selectedCategories.join(","),s=this.selectedCollege?`&college=${this.selectedCollege}`:"",a=encodeURIComponent(this.searchQuery),o=encodeURIComponent(this.teacherQuery),n=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/list/courses?search=${a}&teacher=${o}&sortBy=${e}&sort=${this.sortOrder}&category=${t}${s}&page=${this.currentPage}`),i=await n.json();this.courses=i.courses,this.currentPage=i.currentPage,this.totalPages=i.totalPages},getPaginationPages(){const e=[],t=this.totalPages,s=this.currentPage,a=this.maxVisiblePages;if(t<=a)for(let o=1;o<=t;o++)e.push(o);else{let o=s-Math.floor(a/2);o=Math.max(o,1);let n=o+a-1;n>t&&(n=t,o=Math.max(n-a+1,1));for(let t=o;t<=n;t++)e.push(t)}return e},searchCourses(){this.currentPage=1,this.fetchCourses()},goToPage(e){e<1||e>this.totalPages||(this.currentPage=e,this.fetchCourses())},showCourseDetail(e){this.$router.push(`/detail/${e.course_id}`)},formatTopComment(e){if(!e)return"";let t=0,s="";for(let a=0;a255?1:.5;if(t+o>29)return s+"...";t+=o,s+=e[a]}return s},getCategoryName(e){const t={9:"数学与自然科学类",10:"人文社会科学类",11:"学科基础类",12:"专业方向类",13:"实践类"};return t[e]||"未知分类"},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"}}};const zt=(0,C.A)(At,[["render",Ft],["__scopeId","data-v-3228e625"]]);var Nt=zt;const Wt={class:"sidebar"},Ut={class:"header"},Ot={class:"status-text"},Vt={key:0,class:"no-conversations"},Rt=["onClick"],Dt={class:"conversation-name"},qt={key:0,class:"new-message-label"},Bt={class:"conversation-updated-at"},Qt={class:"conversation-last-message"},Jt={class:"chat-container"},Kt={class:"conversation-info"},Ht={class:"message-bubble"},Gt={key:0},Yt={class:"input-container"};function Zt(e,t,s,a,n,i){const r=(0,o.g2)("el-scrollbar"),c=(0,o.g2)("el-button"),u=(0,o.g2)("el-input"),d=(0,o.g2)("el-tooltip"),h=(0,o.g2)("CourseDetailModal");return(0,o.uX)(),(0,o.CE)("div",{class:(0,l.C4)(["chat-page",{"mobile-chat-active":n.activeConversation}])},[(0,o.Lk)("div",Wt,[(0,o.Lk)("h3",Ut,[t[3]||(t[3]=(0,o.eW)(" 会话列表 ")),(0,o.Lk)("span",{class:(0,l.C4)(["connection-status",{connected:n.isConnected,disconnected:!n.isConnected}])},[(0,o.Lk)("span",{class:(0,l.C4)(["status-indicator",{connected:n.isConnected,disconnected:!n.isConnected}])},null,2),(0,o.Lk)("span",Ot,(0,l.v_)(n.isConnected?"即时聊天已连接":"即时聊天已断开,正在重新连接..."),1)],2)]),(0,o.bF)(r,null,{default:(0,o.k6)((()=>[0===n.conversations.length?((0,o.uX)(),(0,o.CE)("div",Vt," 还没有会话,快去通过评论发起聊天吧! ")):((0,o.uX)(!0),(0,o.CE)(o.FK,{key:1},(0,o.pI)(n.conversations,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.conversation_id,class:(0,l.C4)(["conversation-item",e.conversation_id===n.activeConversation?"active":""]),onClick:t=>i.selectConversation(e.conversation_id)},[(0,o.Lk)("div",Dt,[(0,o.eW)((0,l.v_)(e.course_name)+" ",1),(0,o.Lk)("span",{class:(0,l.C4)(["role-label",{owner:"owner"===e.role,member:"member"===e.role}])},(0,l.v_)("owner"===e.role?"我发起的":"我收到的"),3),e.is_read?(0,o.Q3)("",!0):((0,o.uX)(),(0,o.CE)("span",qt,"新消息"))]),(0,o.Lk)("small",Bt,"更新时间: "+(0,l.v_)(i.formatDate(e.updated_at)),1),t[4]||(t[4]=(0,o.Lk)("br",null,null,-1)),(0,o.Lk)("small",Qt,(0,l.v_)(e.latest_sender?"我:":"对方:")+(0,l.v_)(e.content||"还没有消息哦,快去通过某条课程评论发起聊天吧!"),1)],10,Rt)))),128))])),_:1})]),(0,o.Lk)("div",Jt,[(0,o.Lk)("div",Kt,[(0,o.Lk)("button",{class:"mobile-back-btn",onClick:t[0]||(t[0]=e=>n.activeConversation=null)}," < 返回 "),(0,o.Lk)("span",null,(0,l.v_)(null!==n.rating?"该用户对课程评分为 "+n.rating.toFixed(1):"该用户暂未对课程进行评分"),1),(0,o.bF)(c,{onClick:t[1]||(t[1]=e=>n.selectedCourseId&&i.loadCourseDetail(n.selectedCourseId))},{default:(0,o.k6)((()=>t[5]||(t[5]=[(0,o.eW)("查看课程")]))),_:1})]),(0,o.bF)(r,{ref:"messageScrollbar",class:"message-list"},{default:(0,o.k6)((()=>[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(n.messages,((e,t)=>((0,o.uX)(),(0,o.CE)("div",{key:t,class:(0,l.C4)(["message",1===e.sender?"self":"other"])},[(0,o.Lk)("div",Ht,[(0,o.Lk)("span",null,(0,l.v_)(e.content),1),(0,o.Lk)("div",{class:(0,l.C4)(["message-info",1===e.sender?"align-right":"align-left"])},[(0,o.Lk)("small",null,(0,l.v_)(i.formatDate(e.created_at)),1),1===e.sender?((0,o.uX)(),(0,o.CE)("small",Gt,(0,l.v_)(e.is_read?"已读":"未读"),1)):(0,o.Q3)("",!0)],2)])],2)))),128))])),_:1},512),(0,o.Lk)("div",Yt,[(0,o.bF)(u,{modelValue:n.newMessage,"onUpdate:modelValue":t[2]||(t[2]=e=>n.newMessage=e),type:"textarea",rows:"2",placeholder:"请输入您的消息,按Enter换行,Ctrl+Enter发送。",class:"locked-input",onKeydown:i.handleKeyDown},null,8,["modelValue","onKeydown"]),(0,o.bF)(d,{content:"Ctrl + Enter",placement:"top"},{default:(0,o.k6)((()=>[(0,o.bF)(c,{onClick:i.sendMessage,type:"primary"},{default:(0,o.k6)((()=>t[6]||(t[6]=[(0,o.eW)("发送")]))),_:1},8,["onClick"])])),_:1})])]),n.selectedCourse?((0,o.uX)(),(0,o.Wv)(h,{key:0,isVisible:n.showDetail,course:n.selectedCourse,onClose:i.closeCourseDetail},null,8,["isVisible","course","onClose"])):(0,o.Q3)("",!0)],2)}var es=s(4373);const ts={key:0,class:"modal-overlay"},ss={class:"modal-content"},as={key:0,class:"loading"},os={key:1,class:"course-detail"},ns={key:0,class:"share-modal"},is={key:1,class:"error-modal"},rs={class:"rating-section"},cs={class:"total-rating"},ls={class:"progress-container"},us={class:"stars"},ds=["onMouseover","onClick"],hs={class:"ai-summary"},ms={key:0,class:"typing-cursor"},ps={class:"comment-section"},gs={class:"sort-options"},ks={key:0,class:"comments-list"},vs={class:"comment-meta"},Cs={class:"comment-time",style:{"margin-left":"10px"}},bs=["onClick"],ys={style:{"margin-top":"8px"}},fs={class:"comment-actions"},Ls={style:{color:"red"}},ws=["onClick"],_s=["onClick"],Ss={key:1,class:"no-comments"},Es={key:2,class:"chat-modal-overlay"},xs={class:"chat-modal-content"},Ps={class:"chat-modal-actions"},Ms=["disabled"],Ts={key:3,class:"chat-modal-overlay"},Is={class:"chat-modal-content"},Xs={class:"chat-modal-actions"},js={class:"new-comment"};function $s(e,t,s,n,i,r){const c=(0,o.g2)("el-progress");return s.isVisible?((0,o.uX)(),(0,o.CE)("div",ts,[(0,o.Lk)("div",ss,[(0,o.Lk)("span",{class:"close",onClick:t[0]||(t[0]=(...e)=>r.closeModal&&r.closeModal(...e))},"×"),i.loading?((0,o.uX)(),(0,o.CE)("div",as,t[16]||(t[16]=[(0,o.Lk)("p",null,"加载中...",-1)]))):(0,o.Q3)("",!0),!i.loading&&i.course&&i.course.course_id?((0,o.uX)(),(0,o.CE)("div",os,[(0,o.Lk)("h3",null,[(0,o.eW)((0,l.v_)(i.course.course_name)+" ",1),i.course.titles&&i.course.titles.length>0?((0,o.uX)(!0),(0,o.CE)(o.FK,{key:0},(0,o.pI)(i.course.titles,(e=>((0,o.uX)(),(0,o.CE)("span",{key:e.title,class:"course-title",style:(0,l.Tr)({borderColor:e.color,color:e.color})},(0,l.v_)(e.title),5)))),128)):(0,o.Q3)("",!0),(0,o.Lk)("button",{class:"share-btn",onClick:t[1]||(t[1]=(...e)=>r.shareCourse&&r.shareCourse(...e))},"分享给好友")]),(0,o.Lk)("p",null,[t[17]||(t[17]=(0,o.Lk)("strong",null,"分类:",-1)),(0,o.eW)(" "+(0,l.v_)(r.getCategoryName(i.course.category_id)),1)]),(0,o.Lk)("p",null,[t[18]||(t[18]=(0,o.Lk)("strong",null,"教师:",-1)),(0,o.eW)(" "+(0,l.v_)(i.course.teachers),1)]),(0,o.Lk)("p",null,[t[19]||(t[19]=(0,o.Lk)("strong",null,"开课院系:",-1)),(0,o.eW)(" "+(0,l.v_)(r.getCollegeName(i.course.college)),1)]),i.showShareModal?((0,o.uX)(),(0,o.CE)("div",ns," 链接复制成功,快去分享给其他小伙伴吧! ")):(0,o.Q3)("",!0),i.showErrorModal?((0,o.uX)(),(0,o.CE)("div",is," 获取评论数据失败,正在刷新页面... ")):(0,o.Q3)("",!0),(0,o.Lk)("div",rs,[(0,o.Lk)("h4",null,"课程实时平均分 ("+(0,l.v_)(i.course.rating_count)+"人评分)",1),(0,o.Lk)("div",cs,(0,l.v_)(i.totalRating),1),(0,o.Lk)("div",ls,[(0,o.bF)(c,{class:"progress",percentage:i.fiveStarPercent,status:"success","text-inside":""},{default:(0,o.k6)((()=>[(0,o.eW)("5星: "+(0,l.v_)(i.fiveStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,o.bF)(c,{class:"progress",percentage:i.fourStarPercent,status:"success","text-inside":""},{default:(0,o.k6)((()=>[(0,o.eW)("4星: "+(0,l.v_)(i.fourStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,o.bF)(c,{class:"progress",percentage:i.threeStarPercent,status:"warning","text-inside":""},{default:(0,o.k6)((()=>[(0,o.eW)("3星: "+(0,l.v_)(i.threeStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,o.bF)(c,{class:"progress",percentage:i.twoStarPercent,status:"warning","text-inside":""},{default:(0,o.k6)((()=>[(0,o.eW)("2星: "+(0,l.v_)(i.twoStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,o.bF)(c,{class:"progress",percentage:i.oneStarPercent,status:"exception","text-inside":""},{default:(0,o.k6)((()=>[(0,o.eW)("1星: "+(0,l.v_)(i.oneStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"])]),(0,o.Lk)("div",us,[((0,o.uX)(),(0,o.CE)(o.FK,null,(0,o.pI)(5,(e=>(0,o.Lk)("span",{key:e,class:(0,l.C4)({highlighted:e<=i.userRating}),onMouseover:t=>r.highlightStars(e),onMouseout:t[2]||(t[2]=(...e)=>r.resetStars&&r.resetStars(...e)),onClick:t=>r.confirmRating(e)}," ★ ",42,ds))),64))])]),(0,o.Lk)("p",hs,[t[20]||(t[20]=(0,o.Lk)("span",{style:{display:"block","margin-bottom":"-15px"}},[(0,o.Lk)("strong",null,"AI课程总结"),(0,o.Lk)("span",{style:{color:"white","font-size":"8px","margin-left":"5px","border-radius":"4px",padding:"1px 4px","background-color":"red","vertical-align":"super"}},"Beta"),(0,o.Lk)("span",{style:{"font-size":"12px","margin-left":"5px"}},[(0,o.eW)(" 内容由 "),(0,o.Lk)("img",{src:"https://download.东北大学.com/course_system/deepseek.svg",style:{height:"16px","vertical-align":"middle"}}),(0,o.eW)(" DeepSeek V3 生成,仅供参考 ")])],-1)),t[21]||(t[21]=(0,o.Lk)("br",null,null,-1)),i.displayedSummary?((0,o.uX)(),(0,o.CE)(o.FK,{key:0},[(0,o.eW)((0,l.v_)(i.displayedSummary),1),i.isTyping?((0,o.uX)(),(0,o.CE)("span",ms,"|")):(0,o.Q3)("",!0)],64)):((0,o.uX)(),(0,o.CE)(o.FK,{key:1},[(0,o.eW)(" 当前课程的评分和评论数据过少,暂不能生成AI总结。 ")],64))])])):(0,o.Q3)("",!0),(0,o.Lk)("div",ps,[(0,o.Lk)("div",gs,[(0,o.Lk)("label",null,[(0,o.bo)((0,o.Lk)("input",{type:"radio",value:"like_count","onUpdate:modelValue":t[3]||(t[3]=e=>i.sortBy=e),onChange:t[4]||(t[4]=(...e)=>r.fetchComments&&r.fetchComments(...e))},null,544),[[a.XL,i.sortBy]]),t[22]||(t[22]=(0,o.eW)(" 赞数最多优先"))]),(0,o.Lk)("label",null,[(0,o.bo)((0,o.Lk)("input",{type:"radio",value:"comment_time","onUpdate:modelValue":t[5]||(t[5]=e=>i.sortBy=e),onChange:t[6]||(t[6]=(...e)=>r.fetchComments&&r.fetchComments(...e))},null,544),[[a.XL,i.sortBy]]),t[23]||(t[23]=(0,o.eW)(" 最新评论优先"))])]),r.filteredComments?((0,o.uX)(),(0,o.CE)("div",ks,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.comments,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.comment_id,class:"comment"},[(0,o.Lk)("div",vs,[(0,o.Lk)("strong",null,(0,l.v_)(e.nickname),1),(0,o.Lk)("span",Cs,"发表于 "+(0,l.v_)(r.formatTime(e.comment_time)),1),(0,o.Lk)("span",{class:(0,l.C4)(["like-section",{liked:e.is_liked}]),onClick:t=>r.toggleLike(e)}," ❤ "+(0,l.v_)(e.like_count),11,bs)]),(0,o.Lk)("div",ys,(0,l.v_)(e.comment_content),1),(0,o.Lk)("div",fs,[(0,o.Lk)("span",null,[t[24]||(t[24]=(0,o.eW)("评分: ")),(0,o.Lk)("strong",Ls,(0,l.v_)(e.rating),1)]),e.deleteable?((0,o.uX)(),(0,o.CE)("button",{key:0,onClick:t=>r.deleteComment(e.comment_id),class:"delete-btn"}," 删除 ",8,ws)):((0,o.uX)(),(0,o.CE)("button",{key:1,class:"chat-start-btn",onClick:t=>r.openChatModal(e.comment_id)}," 发起聊天 ",8,_s))])])))),128))])):((0,o.uX)(),(0,o.CE)("p",Ss,"本课程暂无评论。")),i.isChatModalVisible?((0,o.uX)(),(0,o.CE)("div",Es,[(0,o.Lk)("div",xs,[(0,o.Lk)("span",{class:"chat-close-btn",onClick:t[7]||(t[7]=(...e)=>r.closeChatModal&&r.closeChatModal(...e))},"×"),t[25]||(t[25]=(0,o.Lk)("h3",null,"发起聊天",-1)),(0,o.bo)((0,o.Lk)("textarea",{"onUpdate:modelValue":t[8]||(t[8]=e=>i.chatMessage=e),placeholder:"请输入聊天内容(至少6个字符)",class:"chat-textarea"},null,512),[[a.Jo,i.chatMessage]]),(0,o.Lk)("div",Ps,[(0,o.Lk)("button",{onClick:t[9]||(t[9]=(...e)=>r.submitChat&&r.submitChat(...e)),disabled:i.chatMessage.length<6},"发起",8,Ms)])])])):(0,o.Q3)("",!0),i.isConversationExistsModalVisible?((0,o.uX)(),(0,o.CE)("div",Ts,[(0,o.Lk)("div",Is,[(0,o.Lk)("span",{class:"chat-close-btn",onClick:t[10]||(t[10]=(...e)=>r.closeConversationExistsModal&&r.closeConversationExistsModal(...e))},"×"),t[26]||(t[26]=(0,o.Lk)("h3",null,"在此课程下,您与此用户已有会话!",-1)),(0,o.Lk)("div",Xs,[(0,o.Lk)("button",{onClick:t[11]||(t[11]=e=>r.navigateToConversation(i.existingConversationId))},"进入会话"),(0,o.Lk)("button",{onClick:t[12]||(t[12]=(...e)=>r.closeConversationExistsModal&&r.closeConversationExistsModal(...e))},"取消")])])])):(0,o.Q3)("",!0),(0,o.Lk)("div",js,[(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[13]||(t[13]=e=>i.nickname=e),placeholder:"一句话概括您的评论,如:被x老师伤透了心"},null,512),[[a.Jo,i.nickname]]),(0,o.bo)((0,o.Lk)("textarea",{"onUpdate:modelValue":t[14]||(t[14]=e=>i.commentContent=e),placeholder:"我们推荐您分享本课程的课程内容、学习难度、考核方式和给分好坏,以帮助更多同学做出判断。支持删除自己的评论。",style:{resize:"none",height:"50px"}},null,512),[[a.Jo,i.commentContent]]),(0,o.Lk)("button",{onClick:t[15]||(t[15]=(...e)=>r.submitComment&&r.submitComment(...e))},"提交评论")])])])])):(0,o.Q3)("",!0)}var Fs={props:{isVisible:{type:Boolean,required:!0},courseId:{type:[Number,String],required:!0}},data(){return{loading:!1,course:{},token:null,userRating:0,totalRating:0,fiveStarPercent:0,fourStarPercent:0,threeStarPercent:0,twoStarPercent:0,oneStarPercent:0,comments:[],nickname:"",commentContent:"",sortBy:"like_count",showShareModal:!1,cachedEmail:null,isChatModalVisible:!1,isConversationExistsModalVisible:!1,chatMessage:"",currentCommentId:null,existingConversationId:null,showErrorModal:!1,aiSummary:null,displayedSummary:"",isTyping:!1,shouldStopTyping:!1}},watch:{courseId:{immediate:!0,handler(e){e&&this.isVisible&&this.loadCourseData()}},isVisible(e){e&&this.courseId&&this.loadCourseData()},displayedSummary(){this.isTyping&&this.$nextTick((()=>{const e=document.querySelector(".course-detail");e&&(e.scrollTop=e.scrollHeight)}))}},computed:{filteredComments(){return this.comments.length>0?this.comments:null}},methods:{async loadCourseData(){if(this.courseId){this.loading=!0,this.course={},this.aiSummary=null,this.displayedSummary="",this.isTyping=!1,this.shouldStopTyping=!1;try{const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${this.courseId}`);if(!e.ok)throw new Error("Failed to fetch course detail");this.course=await e.json(),this.getToken(),await Promise.all([this.fetchAndCacheEmail(),this.fetchRatingDistribution(),this.fetchUserRating(),this.fetchComments(),this.fetchAISummary()])}catch(e){console.error("Error loading course data:",e)}finally{this.loading=!1}}},getToken(){const e=document.cookie.split("; ").find((e=>e.startsWith("token=")));e?this.token=e.split("=")[1]:(console.error("Token not found in cookies"),this.token=null)},closeModal(){this.shouldStopTyping=!0,this.isTyping=!1,this.displayedSummary="",this.aiSummary=null,this.$emit("close")},getCategoryName(e){const t={1:"选修课-通识选修类",2:"选修课-人文选修类",3:"选修课-专业方向类",4:"选修课-体育类",5:"选修课-学科基础类",6:"选修课-暑期国际课",7:"选修课-数学与自然科学类",8:"选修课-重修专栏",9:"必修课-数学与自然科学类",10:"必修课-人文社会科学类",11:"必修课-学科基础类",12:"必修课-专业方向类",13:"必修课-实践类"};return t[e]||"未知分类"},async fetchRatingDistribution(){const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-course-ratings-distribution?course_id=${this.course.course_id}`);if(e.ok){const t=await e.json();this.totalRating=t.total_rating||0,this.fiveStarPercent=100*t.five_stars,this.fourStarPercent=100*t.four_stars,this.threeStarPercent=100*t.three_stars,this.twoStarPercent=100*t.two_stars,this.oneStarPercent=100*t.one_star}else 404===e.status&&(this.totalRating=0,this.fiveStarPercent=0,this.fourStarPercent=0,this.threeStarPercent=0,this.twoStarPercent=0,this.oneStarPercent=0)},async fetchUserRating(){const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-user-rating?course_id=${this.course.course_id}`,{headers:{Authorization:this.token}});if(200===e.status){const t=await e.json();this.userRating=t.rating}else this.userRating=0},highlightStars(e){this.userRating=e},resetStars(){this.fetchUserRating()},confirmRating(e){confirm(`您确定要给课程 "${this.course.course_name}" 评分:${e}.0 吗?如您之前有评分记录,此评分将覆盖之前的评分。`)&&this.submitRating(e)},async submitRating(e){const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.course.course_id,rating:e})});t.ok&&(this.fetchRatingDistribution(),this.fetchUserRating())},async typewriterEffect(e,t=10){this.isTyping=!0,this.displayedSummary="",this.shouldStopTyping=!1;for(let s=0;ssetTimeout(e,t)))}this.isTyping=!1},async fetchAISummary(){try{const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/ai_summary/summary?course_id=${this.course.course_id}`);if(!e.ok){if(404===e.status)return this.aiSummary=null,void(this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。");throw new Error("获取AI总结失败")}const t=await e.json();t.summary?(this.aiSummary=t.summary,await this.typewriterEffect(this.aiSummary)):this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。"}catch(e){console.error("生成AI总结失败:",e),this.displayedSummary="生成AI总结时出错,请稍后再试。"}},async fetchComments(){try{if(!this.token)return this.showErrorModal=!0,void setTimeout((()=>{window.location.reload()}),2e3);const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-comments?course_id=${this.course.course_id}&sort_by=${this.sortBy}`,{headers:{Authorization:this.token}});if(403===e.status)return this.showErrorModal=!0,void setTimeout((()=>{window.location.reload()}),2e3);if(404===e.status)return void(this.comments=[]);if(!e.ok)throw new Error("获取评论失败");const t=await e.json();this.comments=t.comments}catch(e){console.error("获取评论失败:",e),this.showErrorModal=!0,setTimeout((()=>{window.location.reload()}),2e3)}},async toggleLike(e){e.is_liked?await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/unlike-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e.comment_id})}):await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/like-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e.comment_id})}),this.fetchComments()},async submitComment(){this.nickname.length<3||this.commentContent.length<6?alert("您的昵称请至少包含3个字符,评论请至少包含6个字符。"):(await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.course.course_id,nickname:this.nickname,comment_content:this.commentContent})}),this.fetchComments(),this.nickname="",this.commentContent="")},formatTime(e){const t=new Date(e),s=t.getFullYear(),a=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0"),n=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${s}-${a}-${o} ${n}:${i}`},async fetchAndCacheEmail(){if(!this.cachedEmail)if(this.token)try{const e=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/verifyToken",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token}}),t=await e.json();e.ok&&t.email?this.cachedEmail=t.email:console.error("JWT验证失败或未找到邮箱")}catch(e){console.error("JWT验证时出错:",e)}else console.error("未找到JWT信息")},getUserEmailFromCookie(){return this.cachedEmail?this.cachedEmail:(console.error("邮箱尚未缓存"),"")},base64Encode(e){return btoa(e)},shareCourse(){const e=this.course.course_name,t=this.base64Encode(this.course.course_id.toString());let s="";s=0!==this.totalRating?`我在NEU小站为课程【${e}】评分,当前评分【${this.totalRating}】,点击【https://course.xn--xhq44jb2fzpc.com/courses?c=${t}】加入评分吧!`:`我在NEU小站为课程【${e}】评分,点击【https://course.xn--xhq44jb2fzpc.com/courses?c=${t}】加入评分吧!`,this.copyToClipboard(s),this.showShareModal=!0,setTimeout((()=>{this.showShareModal=!1}),3e3)},copyToClipboard(e){const t=document.createElement("textarea");t.value=e,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"},openChatModal(e){this.currentCommentId=e,this.chatMessage="",this.isChatModalVisible=!0},closeChatModal(){this.isChatModalVisible=!1},closeConversationExistsModal(){this.isConversationExistsModalVisible=!1},async submitChat(){if(this.chatMessage.length<6)alert("聊天内容需至少6个字符");else try{const e=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/chat/start-conversation",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:this.currentCommentId,content:this.chatMessage})}),t=await e.json();e.ok&&"Conversation started successfully"===t.message?this.$router.push(`/chat?mid=${t.conversation_id}`):e.ok&&"Conversation already exists"===t.message?(this.existingConversationId=t.conversation_id,this.isConversationExistsModalVisible=!0):"Recipient account status is abnormal, cannot create a conversation"===t.error?alert("此账号状态异常,暂时无法发起聊天!"):"Cannot start a conversation with yourself!"===t.error?alert("不能向自己发起聊天!"):alert("发起会话失败,请稍后再试")}catch(e){console.error("Error starting conversation:",e),alert("发起会话失败,请稍后再试")}finally{this.closeChatModal()}},navigateToConversation(e){this.$router.push(`/chat?mid=${e}`),this.closeConversationExistsModal()},async deleteComment(e){const t=confirm("确定删除评论吗?");if(t)try{const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/delete-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e})});if(t.ok)this.fetchComments();else{const e=await t.json();alert(e.error||"删除评论失败")}}catch(s){console.error("删除评论出错:",s),alert("删除评论失败")}}}};const As=(0,C.A)(Fs,[["render",$s],["__scopeId","data-v-9c153036"]]);var zs=As,Ns={components:{CourseDetailModal:zs},data(){return{userId:"",activeConversation:null,conversations:[],messages:[],newMessage:"",socket:null,rating:null,selectedCourse:null,selectedCourseId:0,showDetail:!1,isConnected:!1}},async activated(){await this.fetchConversations(),this.activeConversation&&await this.selectConversation(this.activeConversation)},async mounted(){try{const e=this.getCookie("token");if(!e)throw new Error("JWT not found in cookies");const t=JSON.parse(atob(e.split(".")[1]));this.userId=t.id,await this.fetchConversations(),this.checkAndSwitchConversation(),this.initializeWebSocket()}catch(e){console.error("Failed to initialize chat page:",e.message)}},beforeUnmount(){this.socket&&this.socket.close()},methods:{async fetchConversations(){try{const e=await es.A.get("/chat/conversations",{headers:{Authorization:this.getCookie("token")}});this.conversations=[...e.data.conversations]}catch(e){console.error("Failed to fetch conversations:",e)}},formatDate(e){const t=new Date(e);return t.toLocaleString()},async loadCourseDetail(e){try{const t=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${e}`),s=await t.json();this.selectedCourse=s,this.showDetail=!0}catch(t){console.error("Error loading course details:",t)}},closeCourseDetail(){this.showDetail=!1,this.selectedCourse=null},initializeWebSocket(){const e=this.getCookie("token");if(!e)return void console.error("WebSocket initialization failed: No token found");const t=`${"https:"===window.location.protocol?"wss://coursesystem.xn--xhq44jb2fzpc.com":"ws://49.232.202.164:8080"}/chat?token=${e}`;console.log(`Attempting to connect to WebSocket at: ${t}`),this.socket=new WebSocket(t),this.socket.onopen=()=>{this.isConnected=!0,console.log("WebSocket connected")},this.socket.onmessage=async e=>{try{const t=JSON.parse(e.data);switch(console.log("Received WebSocket message:",t),t.type){case"new_conversation":await this.fetchConversations(),t.conversation_id===this.activeConversation&&await this.selectConversation(t.conversation_id);break;case"new_message":await this.fetchConversations(),t.conversation_id===this.activeConversation&&await this.selectConversation(t.conversation_id);break;case"message_read":if(t.conversation_id===this.activeConversation){const e=this.messages.findIndex((e=>e.message_id===t.message_id&&1===e.sender));-1!==e&&this.$set(this.messages[e],"is_read",!0)}break;case"conversation_read":t.conversation_id===this.activeConversation&&this.messages.forEach((e=>{1===e.sender&&t.message_ids.includes(e.message_id)&&(e.is_read=!0)}));break;default:console.warn(`Unknown WebSocket message type: ${t.type}`)}}catch(t){console.error("Error processing WebSocket message:",t)}},this.socket.onclose=e=>{this.isConnected=!1,console.warn(`WebSocket disconnected: Code ${e.code}, Reason: ${e.reason}`),this.reconnectWebSocket()},this.socket.onerror=e=>{console.error("WebSocket error:",e)}},reconnectWebSocket(){console.warn("Attempting to reconnect WebSocket..."),setTimeout((async()=>{try{this.initializeWebSocket();const e=new Promise(((e,t)=>{const s=setInterval((()=>{this.socket&&this.socket.readyState===WebSocket.OPEN&&(clearInterval(s),e())}),500);setTimeout((()=>{clearInterval(s),t(new Error("WebSocket reconnect timeout"))}),1e4)}));await e,this.isConnected=!0,console.log("WebSocket reconnected successfully"),await this.fetchConversations(),this.activeConversation&&await this.selectConversation(this.activeConversation)}catch(e){console.error("Failed to reconnect WebSocket:",e)}}),5e3)},async selectConversation(e){this.activeConversation=e;try{const t=this.conversations.find((t=>t.conversation_id===e));if(!t)throw new Error("Conversation not found");this.selectedCourseId=t.course_id;const s=await es.A.get("/chat/conversation-messages",{params:{conversation_id:e,course_name:t.course_name},headers:{Authorization:this.getCookie("token")}});this.messages=[...s.data.messages],this.rating=s.data.rating||null,this.$nextTick((()=>{this.scrollToBottom()})),await this.markMessagesAsRead()}catch(t){console.error("Failed to fetch conversation messages:",t)}},async markMessagesAsRead(){try{await es.A.post("/chat/read-conversation",{conversation_id:this.activeConversation},{headers:{Authorization:this.getCookie("token")}}),this.messages.forEach((e=>{0!==e.sender||e.is_read||(e.is_read=!0)}))}catch(e){console.error("Failed to mark messages as read:",e)}},async sendMessage(){if(!this.newMessage.trim())return;const e=this.newMessage;this.newMessage="";try{const t=await es.A.post("/chat/send-message",{conversation_id:this.activeConversation,content:e},{headers:{Authorization:this.getCookie("token")}});this.messages.push({message_id:t.data.message_id,content:e,sender:1,created_at:(new Date).toISOString(),is_read:!1}),this.$nextTick((()=>{this.scrollToBottom()})),await this.markMessagesAsRead(),await this.fetchConversations()}catch(t){console.error("Failed to send message:",t)}},scrollToBottom(){setTimeout((()=>{const e=this.$refs.messageScrollbar;if(e){const t=e.$el.querySelector(".el-scrollbar__wrap");t&&(t.scrollTop=t.scrollHeight)}}),50)},handleKeyDown(e){e.ctrlKey&&"Enter"===e.key&&this.sendMessage()},getCookie(e){const t=document.cookie.split("; ");for(let s=0;se.conversation_id===t));s?await this.selectConversation(t):console.warn("Conversation not found for ID:",t)}}};const Ws=(0,C.A)(Ns,[["render",Zt],["__scopeId","data-v-38851032"]]);var Us=Ws;const Os={class:"about-container"},Vs={class:"about-page"},Rs={class:"version-timeline"};function Ds(e,t){const s=(0,o.g2)("el-timeline-item"),a=(0,o.g2)("el-timeline");return(0,o.uX)(),(0,o.CE)("div",Os,[(0,o.Lk)("div",Vs,[t[6]||(t[6]=(0,o.Lk)("div",{class:"project-intro"},[(0,o.Lk)("h2",null,"关于本项目"),(0,o.Lk)("div",{class:"intro-content"},[(0,o.Lk)("p",null,"NEU小站课程评分系统是专门为东北大学学生设计的课程评价平台。本系统采用全匿名方式,学生可以匿名对课程进行评分和发表评论,帮助其他同学更好地了解课程信息。"),(0,o.Lk)("p",null,"系统支持选修课和必修课的评分,包括通识选修、人文选修、专业方向等多个类别。为了保护用户隐私,发表评论时不会显示用户在NEU小站的用户名,每次评论的昵称均由用户自行定义。"),(0,o.Lk)("p",null,"本系统仅对完成NEU小站校园认证的用户开放,确保信息的真实性和可靠性。未来本系统还计划为校内用户开放评分数据下载。")])],-1)),(0,o.Lk)("div",Rs,[t[5]||(t[5]=(0,o.Lk)("h2",null,"更新日志",-1)),(0,o.bF)(a,null,{default:(0,o.k6)((()=>[(0,o.bF)(s,{timestamp:"2025年12月",placement:"top"},{default:(0,o.k6)((()=>t[0]||(t[0]=[(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v2.0"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"重构响应式UI,优化移动端用户体验。暂时下线聊天功能。")])],-1)]))),_:1}),(0,o.bF)(s,{timestamp:"2025年2月",placement:"top"},{default:(0,o.k6)((()=>t[1]||(t[1]=[(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.1.4"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"优化页面样式和用户体验")])],-1),(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.1.3"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"新增AI课程总结功能,接入DeepSeek V3大模型")])],-1)]))),_:1}),(0,o.bF)(s,{timestamp:"2025年1月",placement:"top"},{default:(0,o.k6)((()=>t[2]||(t[2]=[(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.1.2"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"评论区支持删除自己的评论"),(0,o.Lk)("li",null,'优化了"评分由低到高"排序的逻辑,会先展示有评分(评分不为0)的课程'),(0,o.Lk)("li",null,"新增了2024-2025学年春季学期的140门通识选修课")])],-1)]))),_:1}),(0,o.bF)(s,{timestamp:"2024年11月",placement:"top"},{default:(0,o.k6)((()=>t[3]||(t[3]=[(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.1.0"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"新增在线聊天功能"),(0,o.Lk)("li",null,"支持从评论发起聊天")])],-1)]))),_:1}),(0,o.bF)(s,{timestamp:"2024年9月",placement:"top"},{default:(0,o.k6)((()=>t[4]||(t[4]=[(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.0.2"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"新增必修课评分功能"),(0,o.Lk)("li",null,"增加课程类别"),(0,o.Lk)("li",null,"更新用户验证相关接口,增强安全性"),(0,o.Lk)("li",null,"修复部分Bug")])],-1),(0,o.Lk)("div",{class:"version-item"},[(0,o.Lk)("h4",null,"v1.0.0"),(0,o.Lk)("ul",null,[(0,o.Lk)("li",null,"课程评分系统正式上线(测试版)")])],-1)]))),_:1})])),_:1})])])])}const qs={},Bs=(0,C.A)(qs,[["render",Ds],["__scopeId","data-v-5c1b02c2"]]);var Qs=Bs;const Js={class:"course-detail-page"},Ks={key:0,class:"loading-state"},Hs={key:1,class:"container"},Gs={class:"top-section"},Ys={class:"info-card card"},Zs={class:"card-header"},ea={class:"course-name"},ta={key:0,class:"tags"},sa={class:"info-grid"},aa={class:"info-item"},oa={class:"value"},na={class:"info-item"},ia={class:"value"},ra={class:"info-item full-width"},ca={class:"value"},la={class:"action-area"},ua={class:"rating-card card"},da={class:"rating-overview"},ha={class:"total-score"},ma={class:"score"},pa={class:"count"},ga={class:"user-rating-action"},ka={class:"stars interactive"},va=["onMouseover","onClick"],Ca={class:"rating-bars"},ba={class:"bar-row"},ya={class:"percent"},fa={class:"bar-row"},La={class:"percent"},wa={class:"bar-row"},_a={class:"percent"},Sa={class:"bar-row"},Ea={class:"percent"},xa={class:"bar-row"},Pa={class:"percent"},Ma={class:"ai-section card"},Ta={class:"ai-content"},Ia={key:0,class:"summary-text"},Xa={key:0,class:"cursor"},ja={key:1,class:"empty-text"},$a={class:"comments-section card"},Fa={class:"section-header"},Aa={class:"sort-tabs"},za={class:"post-comment"},Na={class:"input-group"},Wa={key:0,class:"comments-list"},Ua={class:"comment-header"},Oa={class:"comment-author"},Va={class:"comment-date"},Ra={class:"comment-body"},Da={class:"comment-footer"},qa={class:"rating-tag"},Ba={class:"actions"},Qa=["onClick"],Ja=["onClick"],Ka={key:1,class:"no-comments"},Ha={key:0,class:"toast"},Ga={key:0,class:"toast error"},Ya={key:2,class:"modal-overlay"},Za={class:"modal-box"},eo={class:"modal-actions"},to=["disabled"],so={key:3,class:"modal-overlay"},ao={class:"modal-box"},oo={class:"modal-actions"};function no(e,t,s,n,i,r){const c=(0,o.g2)("el-progress");return(0,o.uX)(),(0,o.CE)("div",Js,[i.loading?((0,o.uX)(),(0,o.CE)("div",Ks,t[13]||(t[13]=[(0,o.Lk)("div",{class:"spinner"},null,-1),(0,o.Lk)("p",null,"正在加载课程详情...",-1)]))):((0,o.uX)(),(0,o.CE)("div",Hs,[(0,o.Lk)("div",Gs,[(0,o.Lk)("div",Ys,[(0,o.Lk)("div",Zs,[(0,o.Lk)("h1",ea,[(0,o.eW)((0,l.v_)(i.course.course_name)+" ",1),i.course.titles&&i.course.titles.length>0?((0,o.uX)(),(0,o.CE)("div",ta,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.course.titles,(e=>((0,o.uX)(),(0,o.CE)("span",{key:e.title,class:"tag",style:(0,l.Tr)({borderColor:e.color,color:e.color})},(0,l.v_)(e.title),5)))),128))])):(0,o.Q3)("",!0)])]),(0,o.Lk)("div",sa,[(0,o.Lk)("div",aa,[t[14]||(t[14]=(0,o.Lk)("span",{class:"label"},"分类",-1)),(0,o.Lk)("span",oa,(0,l.v_)(r.getCategoryName(i.course.category_id)),1)]),(0,o.Lk)("div",na,[t[15]||(t[15]=(0,o.Lk)("span",{class:"label"},"开课院系",-1)),(0,o.Lk)("span",ia,(0,l.v_)(r.getCollegeName(i.course.college)),1)]),(0,o.Lk)("div",ra,[t[16]||(t[16]=(0,o.Lk)("span",{class:"label"},"教师(团队)",-1)),(0,o.Lk)("span",ca,(0,l.v_)(i.course.teachers),1)])]),(0,o.Lk)("div",la,[(0,o.Lk)("button",{class:"share-btn",onClick:t[0]||(t[0]=(...e)=>r.shareCourse&&r.shareCourse(...e))},t[17]||(t[17]=[(0,o.Lk)("span",{class:"icon"},"🔗",-1),(0,o.eW)(" 复制链接 ")]))])]),(0,o.Lk)("div",ua,[t[24]||(t[24]=(0,o.Lk)("h3",null,"课程评分",-1)),(0,o.Lk)("div",da,[(0,o.Lk)("div",ha,[(0,o.Lk)("span",ma,(0,l.v_)(i.totalRating),1),(0,o.Lk)("span",pa,"("+(0,l.v_)(i.course.rating_count||0)+"人评分)",1)]),(0,o.Lk)("div",ga,[t[18]||(t[18]=(0,o.Lk)("p",null,"您的评分",-1)),(0,o.Lk)("div",ka,[((0,o.uX)(),(0,o.CE)(o.FK,null,(0,o.pI)(5,(e=>(0,o.Lk)("span",{key:e,class:(0,l.C4)({active:e<=i.userRating}),onMouseover:t=>r.highlightStars(e),onMouseout:t[1]||(t[1]=(...e)=>r.resetStars&&r.resetStars(...e)),onClick:t=>r.confirmRating(e)},"★",42,va))),64))])])]),(0,o.Lk)("div",Ca,[(0,o.Lk)("div",ba,[t[19]||(t[19]=(0,o.Lk)("span",{class:"star-label"},"5星",-1)),(0,o.bF)(c,{percentage:i.fiveStarPercent,status:"success","show-text":!1,"stroke-width":8},null,8,["percentage"]),(0,o.Lk)("span",ya,(0,l.v_)(i.fiveStarPercent.toFixed(0))+"%",1)]),(0,o.Lk)("div",fa,[t[20]||(t[20]=(0,o.Lk)("span",{class:"star-label"},"4星",-1)),(0,o.bF)(c,{percentage:i.fourStarPercent,status:"success","show-text":!1,"stroke-width":8},null,8,["percentage"]),(0,o.Lk)("span",La,(0,l.v_)(i.fourStarPercent.toFixed(0))+"%",1)]),(0,o.Lk)("div",wa,[t[21]||(t[21]=(0,o.Lk)("span",{class:"star-label"},"3星",-1)),(0,o.bF)(c,{percentage:i.threeStarPercent,status:"warning","show-text":!1,"stroke-width":8},null,8,["percentage"]),(0,o.Lk)("span",_a,(0,l.v_)(i.threeStarPercent.toFixed(0))+"%",1)]),(0,o.Lk)("div",Sa,[t[22]||(t[22]=(0,o.Lk)("span",{class:"star-label"},"2星",-1)),(0,o.bF)(c,{percentage:i.twoStarPercent,status:"warning","show-text":!1,"stroke-width":8},null,8,["percentage"]),(0,o.Lk)("span",Ea,(0,l.v_)(i.twoStarPercent.toFixed(0))+"%",1)]),(0,o.Lk)("div",xa,[t[23]||(t[23]=(0,o.Lk)("span",{class:"star-label"},"1星",-1)),(0,o.bF)(c,{percentage:i.oneStarPercent,status:"exception","show-text":!1,"stroke-width":8},null,8,["percentage"]),(0,o.Lk)("span",Pa,(0,l.v_)(i.oneStarPercent.toFixed(0))+"%",1)])])])]),(0,o.Lk)("div",Ma,[t[25]||(t[25]=(0,o.Lk)("div",{class:"section-header"},[(0,o.Lk)("h2",null,[(0,o.Lk)("span",{class:"icon"},"🤖"),(0,o.eW)(" AI 课程总结 "),(0,o.Lk)("span",{class:"beta-badge"},"Beta")]),(0,o.Lk)("span",{class:"ai-disclaimer"},"内容由 DeepSeek V3 生成,仅供参考")],-1)),(0,o.Lk)("div",Ta,[i.displayedSummary?((0,o.uX)(),(0,o.CE)("div",Ia,[(0,o.eW)((0,l.v_)(i.displayedSummary),1),i.isTyping?((0,o.uX)(),(0,o.CE)("span",Xa,"|")):(0,o.Q3)("",!0)])):((0,o.uX)(),(0,o.CE)("p",ja,"当前课程的评分和评论数据过少,暂不能生成AI总结。"))])]),(0,o.Lk)("div",$a,[(0,o.Lk)("div",Fa,[t[27]||(t[27]=(0,o.Lk)("h2",null,"课程评论",-1)),(0,o.Lk)("div",Aa,[(0,o.Lk)("span",{class:(0,l.C4)({active:"like_count"===i.sortBy}),onClick:t[2]||(t[2]=e=>r.changeSort("like_count"))},"最热",2),t[26]||(t[26]=(0,o.Lk)("span",{class:"divider"},"|",-1)),(0,o.Lk)("span",{class:(0,l.C4)({active:"comment_time"===i.sortBy}),onClick:t[3]||(t[3]=e=>r.changeSort("comment_time"))},"最新",2)])]),(0,o.Lk)("div",za,[(0,o.Lk)("div",Na,[(0,o.bo)((0,o.Lk)("input",{"onUpdate:modelValue":t[4]||(t[4]=e=>i.nickname=e),placeholder:"一句话概括您的评论",class:"nickname-input"},null,512),[[a.Jo,i.nickname]]),(0,o.bo)((0,o.Lk)("textarea",{"onUpdate:modelValue":t[5]||(t[5]=e=>i.commentContent=e),placeholder:"分享您的课程体验、学习难度、考核方式等...",class:"comment-textarea"},null,512),[[a.Jo,i.commentContent]])]),(0,o.Lk)("button",{onClick:t[6]||(t[6]=(...e)=>r.submitComment&&r.submitComment(...e)),class:"submit-btn"},"提交评论")]),r.filteredComments&&r.filteredComments.length>0?((0,o.uX)(),(0,o.CE)("div",Wa,[((0,o.uX)(!0),(0,o.CE)(o.FK,null,(0,o.pI)(i.comments,(e=>((0,o.uX)(),(0,o.CE)("div",{key:e.comment_id,class:"comment-item"},[(0,o.Lk)("div",Ua,[(0,o.Lk)("span",Oa,(0,l.v_)(e.nickname),1),(0,o.Lk)("span",Va,(0,l.v_)(r.formatTime(e.comment_time)),1)]),(0,o.Lk)("div",Ra,(0,l.v_)(e.comment_content),1),(0,o.Lk)("div",Da,[(0,o.Lk)("div",qa,[t[28]||(t[28]=(0,o.eW)(" 评分: ")),(0,o.Lk)("span",null,(0,l.v_)(e.rating),1)]),(0,o.Lk)("div",Ba,[(0,o.Lk)("span",{class:(0,l.C4)(["like-btn",{liked:e.is_liked}]),onClick:t=>r.toggleLike(e)}," ❤ "+(0,l.v_)(e.like_count),11,Qa),e.deleteable?((0,o.uX)(),(0,o.CE)("button",{key:0,onClick:t=>r.deleteComment(e.comment_id),class:"action-link delete"}," 删除 ",8,Ja)):(0,o.Q3)("",!0)])])])))),128))])):((0,o.uX)(),(0,o.CE)("div",Ka,t[29]||(t[29]=[(0,o.Lk)("p",null,"暂无评论,快来抢沙发吧!",-1)])))])])),(0,o.bF)(a.eB,{name:"fade"},{default:(0,o.k6)((()=>[i.showShareModal?((0,o.uX)(),(0,o.CE)("div",Ha," 链接复制成功,快去分享给其他小伙伴吧! ")):(0,o.Q3)("",!0)])),_:1}),(0,o.bF)(a.eB,{name:"fade"},{default:(0,o.k6)((()=>[i.showErrorModal?((0,o.uX)(),(0,o.CE)("div",Ga," 获取数据失败,正在刷新页面... ")):(0,o.Q3)("",!0)])),_:1}),i.isChatModalVisible?((0,o.uX)(),(0,o.CE)("div",Ya,[(0,o.Lk)("div",Za,[(0,o.Lk)("span",{class:"close-btn",onClick:t[7]||(t[7]=(...e)=>r.closeChatModal&&r.closeChatModal(...e))},"×"),t[30]||(t[30]=(0,o.Lk)("h3",null,"发起聊天",-1)),(0,o.bo)((0,o.Lk)("textarea",{"onUpdate:modelValue":t[8]||(t[8]=e=>i.chatMessage=e),placeholder:"请输入聊天内容(至少6个字符)",class:"modal-textarea"},null,512),[[a.Jo,i.chatMessage]]),(0,o.Lk)("div",eo,[(0,o.Lk)("button",{onClick:t[9]||(t[9]=(...e)=>r.submitChat&&r.submitChat(...e)),disabled:i.chatMessage.length<6,class:"primary-btn"},"发起",8,to)])])])):(0,o.Q3)("",!0),i.isConversationExistsModalVisible?((0,o.uX)(),(0,o.CE)("div",so,[(0,o.Lk)("div",ao,[(0,o.Lk)("span",{class:"close-btn",onClick:t[10]||(t[10]=(...e)=>r.closeConversationExistsModal&&r.closeConversationExistsModal(...e))},"×"),t[31]||(t[31]=(0,o.Lk)("h3",null,"提示",-1)),t[32]||(t[32]=(0,o.Lk)("p",null,"在此课程下,您与此用户已有会话!",-1)),(0,o.Lk)("div",oo,[(0,o.Lk)("button",{onClick:t[11]||(t[11]=e=>r.navigateToConversation(i.existingConversationId)),class:"primary-btn"},"进入会话"),(0,o.Lk)("button",{onClick:t[12]||(t[12]=(...e)=>r.closeConversationExistsModal&&r.closeConversationExistsModal(...e)),class:"secondary-btn"},"取消")])])])):(0,o.Q3)("",!0)])}var io={name:"CourseDetail",data(){return{courseId:null,loading:!0,course:{},token:null,userRating:0,totalRating:0,fiveStarPercent:0,fourStarPercent:0,threeStarPercent:0,twoStarPercent:0,oneStarPercent:0,comments:[],nickname:"",commentContent:"",sortBy:"like_count",showShareModal:!1,cachedEmail:null,isChatModalVisible:!1,isConversationExistsModalVisible:!1,chatMessage:"",currentCommentId:null,existingConversationId:null,showErrorModal:!1,aiSummary:null,displayedSummary:"",isTyping:!1,shouldStopTyping:!1}},computed:{filteredComments(){return this.comments.length>0?this.comments:null}},async created(){this.courseId=this.$route.params.course_id,this.courseId?await this.loadCourseData():(this.loading=!1,this.$router.push("/rating"))},beforeUnmount(){this.shouldStopTyping=!0},methods:{async loadCourseData(){this.loading=!0,this.course={},this.aiSummary=null,this.displayedSummary="",this.isTyping=!1,this.shouldStopTyping=!1;try{const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${this.courseId}`);if(!e.ok)throw new Error("Failed to fetch course detail");this.course=await e.json(),this.getToken(),await Promise.all([this.fetchAndCacheEmail(),this.fetchRatingDistribution(),this.fetchUserRating(),this.fetchComments(),this.fetchAISummary()])}catch(e){console.error("Error loading course data:",e)}finally{this.loading=!1}},getToken(){const e=document.cookie.split("; ").find((e=>e.startsWith("token=")));this.token=e?e.split("=")[1]:null},changeSort(e){this.sortBy!==e&&(this.sortBy=e,this.fetchComments())},getCategoryName(e){const t={1:"选修课-通识选修类",2:"选修课-人文选修类",3:"选修课-专业方向类",4:"选修课-体育类",5:"选修课-学科基础类",6:"选修课-暑期国际课",7:"选修课-数学与自然科学类",8:"选修课-重修专栏",9:"必修课-数学与自然科学类",10:"必修课-人文社会科学类",11:"必修课-学科基础类",12:"必修课-专业方向类",13:"必修课-实践类"};return t[e]||"未知分类"},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"},async fetchRatingDistribution(){const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-course-ratings-distribution?course_id=${this.courseId}`);if(e.ok){const t=await e.json();this.totalRating=t.total_rating||0,this.fiveStarPercent=100*t.five_stars,this.fourStarPercent=100*t.four_stars,this.threeStarPercent=100*t.three_stars,this.twoStarPercent=100*t.two_stars,this.oneStarPercent=100*t.one_star}else this.totalRating=0,this.fiveStarPercent=0,this.fourStarPercent=0,this.threeStarPercent=0,this.twoStarPercent=0,this.oneStarPercent=0},async fetchUserRating(){if(!this.token)return;const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-user-rating?course_id=${this.courseId}`,{headers:{Authorization:this.token}});if(200===e.status){const t=await e.json();this.userRating=t.rating}else this.userRating=0},highlightStars(e){this.userRating=e},resetStars(){this.fetchUserRating()},confirmRating(e){confirm(`您确定要给课程 "${this.course.course_name}" 评分:${e}.0 吗?此评分将覆盖之前的评分。`)&&this.submitRating(e)},async submitRating(e){const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.courseId,rating:e})});t.ok&&(this.fetchRatingDistribution(),this.fetchUserRating())},async typewriterEffect(e,t=10){this.isTyping=!0,this.displayedSummary="",this.shouldStopTyping=!1;for(let s=0;ssetTimeout(e,t)))}this.isTyping=!1},async fetchAISummary(){try{const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/ai_summary/summary?course_id=${this.courseId}`);if(!e.ok)return void(this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。");const t=await e.json();t.summary?(this.aiSummary=t.summary,await this.typewriterEffect(this.aiSummary)):this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。"}catch(e){this.displayedSummary="生成AI总结时出错,请稍后再试。"}},async fetchComments(){try{this.token;const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-comments?course_id=${this.courseId}&sort_by=${this.sortBy}`,{headers:{Authorization:this.token}});if(404===e.status)return void(this.comments=[]);if(!e.ok)throw new Error("获取评论失败");const t=await e.json();this.comments=t.comments}catch(e){console.error(e)}},async toggleLike(e){const t=e.is_liked?"unlike-comment":"like-comment";await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/${t}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e.comment_id})}),this.fetchComments()},async submitComment(){this.nickname.length<2||this.commentContent.length<6?alert("一句话概括请至少包含2个字符,评论请至少包含6个字符。"):(await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.courseId,nickname:this.nickname,comment_content:this.commentContent})}),this.fetchComments(),this.nickname="",this.commentContent="")},async deleteComment(e){if(!confirm("确定删除评论吗?"))return;const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/delete-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e})});t.ok&&this.fetchComments()},formatTime(e){const t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`},async fetchAndCacheEmail(){if(!this.cachedEmail&&this.token)try{const e=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/verifyToken",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token}}),t=await e.json();e.ok&&t.email&&(this.cachedEmail=t.email)}catch(e){console.error(e)}},base64Encode(e){return btoa(e)},shareCourse(){const e=`https://course.xn--xhq44jb2fzpc.com/detail/${this.courseId}`;this.copyToClipboard(e),this.showShareModal=!0,setTimeout((()=>{this.showShareModal=!1}),3e3)},copyToClipboard(e){const t=document.createElement("textarea");t.value=e,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)},openChatModal(e){this.currentCommentId=e,this.chatMessage="",this.isChatModalVisible=!0},closeChatModal(){this.isChatModalVisible=!1},closeConversationExistsModal(){this.isConversationExistsModalVisible=!1},async submitChat(){if(this.chatMessage.length<6)alert("聊天内容需至少6个字符");else try{const e=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/chat/start-conversation",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:this.currentCommentId,content:this.chatMessage})}),t=await e.json();e.ok&&"Conversation started successfully"===t.message?this.$router.push(`/chat?mid=${t.conversation_id}`):e.ok&&"Conversation already exists"===t.message?(this.existingConversationId=t.conversation_id,this.isConversationExistsModalVisible=!0):alert(t.error||"发起会话失败")}catch(e){alert("发起会话失败,请稍后再试")}finally{this.closeChatModal()}},navigateToConversation(e){this.$router.push(`/chat?mid=${e}`),this.closeConversationExistsModal()}}};const ro=(0,C.A)(io,[["render",no],["__scopeId","data-v-2c76732d"]]);var co=ro;const lo=[{path:"/",name:"home",meta:{title:"NEU小站课程评分系统"},component:X},{path:"/courses",name:"course-list",meta:{title:"我的课程 - NEU小站课程评分系统"},component:Ce},{path:"/rating",name:"rating",meta:{title:"选修课列表 - NEU小站课程评分系统"},component:tt},{path:"/ratingforcomp",name:"ratingforcomp",meta:{title:"必修课列表 - NEU小站课程评分系统"},component:Nt},{path:"/chat",name:"chat",meta:{title:"我的聊天 - NEU小站课程评分系统"},component:Us},{path:"/about",name:"about",meta:{title:"关于 - NEU小站课程评分系统"},component:Qs},{path:"/detail/:course_id",name:"course-detail",meta:{title:"课程详情 - NEU小站课程评分系统"},component:co}],uo=(0,S.aE)({history:(0,S.LA)(),routes:lo});uo.beforeEach(((e,t,s)=>{document.title=e.meta.title||"默认标题",s()}));var ho=uo;const mo=(0,a.Ef)(w);mo.use(ho),mo.use(_.A),mo.mount("#app"),es.A.defaults.baseURL="https://coursesystem.xn--xhq44jb2fzpc.com/",mo.config.globalProperties.$axios=es.A}},t={};function s(a){var o=t[a];if(void 0!==o)return o.exports;var n=t[a]={exports:{}};return e[a].call(n.exports,n,n.exports,s),n.exports}s.m=e,function(){var e=[];s.O=function(t,a,o,n){if(!a){var i=1/0;for(u=0;u=n)&&Object.keys(s.O).every((function(e){return s.O[e](a[c])}))?a.splice(c--,1):(r=!1,n0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[a,o,n]}}(),function(){s.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(t,{a:t}),t}}(),function(){s.d=function(e,t){for(var a in t)s.o(t,a)&&!s.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){var e={524:0};s.O.j=function(t){return 0===e[t]};var t=function(t,a){var o,n,i=a[0],r=a[1],c=a[2],l=0;if(i.some((function(t){return 0!==e[t]}))){for(o in r)s.o(r,o)&&(s.m[o]=r[o]);if(c)var u=c(s)}for(t&&t(a);ld.enableDesktopMode&&d.enableDesktopMode(...e)),class:"forbidden-back-btn"},"使用电脑版样式访问")])):u.isAuthorized?((0,a.uX)(),(0,a.CE)("div",i,[(0,a.Lk)("aside",l,[(0,a.bF)(h)]),(0,a.Lk)("main",r,[(0,a.bF)(m)])])):((0,a.uX)(),(0,a.CE)("div",c,t[3]||(t[3]=[(0,a.Fv)('您的访问被拒绝 只有在 NEU小站 完成 校园网或校园邮箱验证 的用户才能访问课程评分系统。
请确保您已完成相关操作,然后重新尝试访问。
返回登录页面 ',4)])))])}function d(e,t,s,o,n,i){const l=(0,a.g2)("el-menu-item"),r=(0,a.g2)("el-menu");return(0,a.uX)(),(0,a.Wv)(r,{"default-active":i.activeMenu,class:"el-menu-vertical-demo","background-color":"#333","text-color":"#fff","active-text-color":"#ffd04b"},{default:(0,a.k6)((()=>[(0,a.bF)(l,{index:"1",onClick:t[0]||(t[0]=e=>i.goTo("home"))},{default:(0,a.k6)((()=>t[6]||(t[6]=[(0,a.Lk)("i",{class:"el-icon-house"},null,-1),(0,a.Lk)("span",null,"使用必看",-1)]))),_:1}),(0,a.bF)(l,{index:"2",onClick:t[1]||(t[1]=e=>i.goTo("rating"))},{default:(0,a.k6)((()=>t[7]||(t[7]=[(0,a.Lk)("i",{class:"el-icon-setting"},null,-1),(0,a.Lk)("span",null,"选修课评分",-1)]))),_:1}),(0,a.bF)(l,{index:"3",onClick:t[2]||(t[2]=e=>i.goTo("ratingforcomp"))},{default:(0,a.k6)((()=>t[8]||(t[8]=[(0,a.Lk)("i",{class:"el-icon-setting"},null,-1),(0,a.Lk)("span",null,"必修课评分",-1)]))),_:1}),(0,a.bF)(l,{index:"4",onClick:t[3]||(t[3]=e=>i.goTo("course-list"))},{default:(0,a.k6)((()=>t[9]||(t[9]=[(0,a.Lk)("i",{class:"el-icon-setting"},null,-1),(0,a.Lk)("span",null,"我的课程",-1)]))),_:1}),(0,a.bF)(l,{index:"5",onClick:t[4]||(t[4]=e=>i.goTo("chat"))},{default:(0,a.k6)((()=>t[10]||(t[10]=[(0,a.Lk)("i",{class:"el-icon-setting"},null,-1),(0,a.Lk)("span",null,"我的聊天",-1)]))),_:1}),(0,a.bF)(l,{index:"6",onClick:t[5]||(t[5]=e=>i.goTo("about"))},{default:(0,a.k6)((()=>t[11]||(t[11]=[(0,a.Lk)("i",{class:"el-icon-info"},null,-1),(0,a.Lk)("span",null,"关于",-1)]))),_:1}),t[12]||(t[12]=(0,a.Lk)("div",{class:"sidebar-footer"},[(0,a.Lk)("span",{class:"footer-title"},"NEU小站课程评分系统 - v1.1"),(0,a.Lk)("div",{class:"footer-info"},[(0,a.eW)(" © 2025 "),(0,a.Lk)("a",{href:"https://www.xn--xhq44jb2fzpc.com/",target:"_blank"},"NEU小站")])],-1))])),_:1},8,["default-active"])}s(4114);var h={name:"SideBar",computed:{activeMenu(){const e=this.$route.name;return"home"===e?"1":"rating"===e?"2":"ratingforcomp"===e?"3":"course-list"===e?"4":"chat"===e?"5":"about"===e?"6":"1"}},methods:{goTo(e){this.$router.push({name:e})}}},m=s(1241);const g=(0,m.A)(h,[["render",d],["__scopeId","data-v-fa32c4be"]]);var p=g,k={name:"App",data(){return{isAuthorized:!1,authChecked:!1,isMobile:!1,forceDesktopMode:!1}},components:{SideBar:p},mounted(){this.checkIfMobile(),this.checkLoginStatus()},methods:{checkIfMobile(){const e=navigator.userAgent||navigator.vendor||window.opera,t=/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(e.toLowerCase()),s="true"===localStorage.getItem("forceDesktopMode");t&&!s?this.isMobile=!0:this.forceDesktopMode=s},enableDesktopMode(){this.forceDesktopMode=!0,localStorage.setItem("forceDesktopMode","true");const e=document.querySelector('meta[name="viewport"]');if(e)e.setAttribute("content","width=1024");else{const e=document.createElement("meta");e.name="viewport",e.content="width=1024",document.head.appendChild(e)}},async checkLoginStatus(){const e=document.cookie.split("; ").reduce(((e,t)=>{const[s,o]=t.split("=");return e[s]=decodeURIComponent(o),e}),{}).token;if(e)try{const t=await fetch("https://newfront.xn--xhq44jb2fzpc.com/user/info",{method:"GET",headers:{Authorization:e}}),s=await t.json();t.ok&&!0===s.activated?this.isAuthorized=!0:console.warn("用户未通过验证:用户未激活")}catch(t){console.error("获取用户信息失败:",t)}finally{this.authChecked=!0}}}};const v=(0,m.A)(k,[["render",u]]);var b=v,C=s(6762),f=(s(4188),s(973)),y=s(4232);const L={key:0},_={id:"homepage-title"},w={key:1};function E(e,t,s,o,n,i){const l=(0,a.g2)("router-link");return n.isLoaded?((0,a.uX)(),(0,a.CE)("div",L,[(0,a.Lk)("div",null,[(0,a.Lk)("h2",_,(0,y.v_)(n.greeting)+", "+(0,y.v_)(n.nickname)+"!",1),t[9]||(t[9]=(0,a.Fv)("欢迎您使用NEU小站课程评分系统!
本系统采用全匿名方式 ,学生可以匿名对课程进行评分和发表评论。每人对每个课程只能评分一次,若需要多次评分,系统将记录用户最后一次提交的评分结果。为保护隐私,发表评论时不会显示用户在NEU小站的用户名,每次评论的昵称均由用户自行定义。
本系统中,课程分为两大类:选修课和必修课。 选修课有8个小类:通识选修、人文选修、专业方向、体育、学科基础、暑期国际课、数学与自然科学、重修专栏。人文选修类包括采用“抢选”方式进行选课的所有选修课,以及“改革开放史”和“社会主义发展史”两门人文社会科学类的选修课。 体育课单独作为一类,不属于人文选修类。重修课程的选课归为选修课的“重修专栏”类别,不属于必修课范畴。 重修专栏可以分享任何类别课程 ,但仅限分享重修体验 。
必修课有5个小类:数学与自然科学、人文社会科学、学科基础、专业方向、实践。如上所述,本系统中重修的必修课程也属于选修课范畴。 特别说明:军训课程属于实践类,系辅导员给分,在创建课程时课程教师请填写辅导员。
",4)),(0,a.Lk)("p",null,[t[1]||(t[1]=(0,a.eW)(" 在创建课程时,请先了解课程的类别,以及课程的")),t[2]||(t[2]=(0,a.Lk)("strong",null,"开课院系",-1)),t[3]||(t[3]=(0,a.eW)(",")),(0,a.bF)(l,{to:"/courses?m=true",class:"guide-link"},{default:(0,a.k6)((()=>t[0]||(t[0]=[(0,a.eW)("点击此处")]))),_:1}),t[4]||(t[4]=(0,a.eW)("查看指引。")),t[5]||(t[5]=(0,a.Lk)("strong",null,'如果同一课程的任课教师不同,用户可以创建多个同名课程,例如"A老师-篮球"和"B老师-篮球"将被视为两个不同的课程。',-1)),t[6]||(t[6]=(0,a.eW)("创建的课程卡片")),t[7]||(t[7]=(0,a.Lk)("strong",null,"需经过管理员审核",-1)),t[8]||(t[8]=(0,a.eW)(',审核进度可在"我的课程"中实时查看。 '))]),t[10]||(t[10]=(0,a.Lk)("p",null,[(0,a.eW)(" 本系统鼓励同学们提供真实、有价值的评分。"),(0,a.Lk)("strong",null,"禁止发布带有侮辱性的人身攻击等恶意评论。"),(0,a.eW)("管理员将对恶意用户进行封禁处理,确保评分系统的文明环境。 ")],-1))])])):((0,a.uX)(),(0,a.CE)("div",w,t[11]||(t[11]=[(0,a.Lk)("p",null,"加载中,请稍后...",-1)])))}var x={data(){return{name:"Homepage",greeting:"",nickname:"",isLoaded:!1}},mounted(){this.setGreeting(),this.fetchNickname(),setTimeout((()=>{this.isLoaded=!0}),300)},methods:{setGreeting(){const e=(new Date).getHours();this.greeting=e<12?"早上好":e<14?"中午好":e<18?"下午好":"晚上好"},async fetchNickname(){const e=document.cookie.split("; ").reduce(((e,t)=>{const[s,o]=t.split("=");return e[s]=decodeURIComponent(o),e}),{}).token;if(e)try{const t=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/avatar/nickname",{method:"GET",headers:{Authorization:e}});if(!t.ok){const e=await t.json();return void console.error("获取昵称失败:",e.message||"未知错误")}const s=await t.json();s.nickname?(this.nickname=s.nickname,console.log("Nickname successfully fetched:",s.nickname)):(this.nickname="默认昵称",console.log("Nickname field is missing. Using default nickname."))}catch(t){console.error("获取昵称时出错:",t)}else console.error("未找到JWT信息")}}};const S=(0,m.A)(x,[["render",E],["__scopeId","data-v-b83355ba"]]);var P=S;const T={key:0,class:"loading-message"},M={key:1,class:"empty-message"},W={key:2,class:"course-table"},X={key:0},I=["onClick"],j={class:"pagination-bar"},D=["onClick"],A={class:"add-course"},F={class:"section-header"},N={class:"input-section"},U=["value"],$={key:4,class:"help-modal"},z={class:"help-modal-content"},V={class:"help-modal-header"};function O(e,t,s,n,i,l){const r=(0,a.g2)("CourseDetailModal");return(0,a.uX)(),(0,a.CE)("div",null,[t[14]||(t[14]=(0,a.Lk)("h2",null,"我添加的课程",-1)),i.isLoaded?0===i.submissions.length?((0,a.uX)(),(0,a.CE)("div",M," 您还没有添加任何课程。 ")):((0,a.uX)(),(0,a.CE)("div",W,[(0,a.Lk)("table",null,[t[7]||(t[7]=(0,a.Lk)("thead",null,[(0,a.Lk)("tr",null,[(0,a.Lk)("th",null,"课程名"),(0,a.Lk)("th",null,"分类"),(0,a.Lk)("th",null,"教师"),(0,a.Lk)("th",null,"开课院系"),(0,a.Lk)("th",null,"提交时间"),(0,a.Lk)("th",null,"状态更新时间"),(0,a.Lk)("th",null,"审核状态")])],-1)),(0,a.Lk)("tbody",null,[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.paginatedSubmissions,(e=>((0,a.uX)(),(0,a.CE)("tr",{key:e.submit_id},[(0,a.Lk)("td",null,[0===e.course_id?((0,a.uX)(),(0,a.CE)("span",X,(0,y.v_)(e.course_name),1)):((0,a.uX)(),(0,a.CE)("span",{key:1,class:"clickable-text",onClick:t=>l.loadCourseDetail(e.course_id)},(0,y.v_)(e.course_name),9,I))]),(0,a.Lk)("td",null,(0,y.v_)(l.getCategoryName(e.category_id)),1),(0,a.Lk)("td",null,(0,y.v_)(e.teachers),1),(0,a.Lk)("td",null,(0,y.v_)(l.getCollegeName(e.college)),1),(0,a.Lk)("td",null,(0,y.v_)(l.formatTime(e.create_time)),1),(0,a.Lk)("td",null,(0,y.v_)(l.formatTime(e.status_update_time)),1),(0,a.Lk)("td",null,(0,y.v_)(e.status),1)])))),128))])]),(0,a.Lk)("div",j,[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(i.totalPages,(e=>((0,a.uX)(),(0,a.CE)("button",{key:e,onClick:t=>l.goToPage(e),class:(0,y.C4)({active:i.currentPage===e})},(0,y.v_)(e),11,D)))),128))])])):((0,a.uX)(),(0,a.CE)("div",T," 加载中,请稍后... ")),(0,a.Lk)("div",A,[(0,a.Lk)("div",F,[t[9]||(t[9]=(0,a.Lk)("h2",null,"我要添加课程",-1)),(0,a.Lk)("button",{class:"help-btn",onClick:t[0]||(t[0]=e=>i.showHelp=!0)},t[8]||(t[8]=[(0,a.Lk)("span",{class:"help-icon"},"?",-1),(0,a.eW)(" 帮助 ")]))]),(0,a.Lk)("div",N,[(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[1]||(t[1]=e=>i.newCourseName=e),type:"text",placeholder:"请输入课程名称"},null,512),[[o.Jo,i.newCourseName]]),(0,a.bo)((0,a.Lk)("select",{"onUpdate:modelValue":t[2]||(t[2]=e=>i.newCategoryId=e)},t[10]||(t[10]=[(0,a.Fv)('请选择课程类别 选修课-通识选修类 选修课-人文选修类 选修课-专业方向类 选修课-体育类 选修课-学科基础类 选修课-暑期国际课 选修课-数学与自然科学类 选修课-重修专栏 必修课-数学与自然科学类 必修课-人文社会科学类 必修课-学科基础类 必修课-专业方向类 必修课-实践类 ',14)]),512),[[o.u1,i.newCategoryId]]),(0,a.bo)((0,a.Lk)("select",{"onUpdate:modelValue":t[3]||(t[3]=e=>i.newCollege=e)},[t[11]||(t[11]=(0,a.Lk)("option",{value:"",disabled:""},"请选择开课院系",-1)),((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.filteredColleges,((e,t)=>((0,a.uX)(),(0,a.CE)("option",{key:t,value:t},(0,y.v_)(e),9,U)))),128))],512),[[o.u1,i.newCollege]]),(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[4]||(t[4]=e=>i.newTeachers=e),type:"text",placeholder:"请输入任课教师(多个教师之间用英文逗号,隔开)"},null,512),[[o.Jo,i.newTeachers]]),(0,a.Lk)("button",{onClick:t[5]||(t[5]=(...e)=>l.submitCourse&&l.submitCourse(...e))},"提交")])]),i.selectedCourse?((0,a.uX)(),(0,a.Wv)(r,{key:3,isVisible:i.showDetail,course:i.selectedCourse,onClose:l.closeCourseDetail},null,8,["isVisible","course","onClose"])):(0,a.Q3)("",!0),i.showHelp?((0,a.uX)(),(0,a.CE)("div",$,[(0,a.Lk)("div",z,[(0,a.Lk)("div",V,[t[12]||(t[12]=(0,a.Lk)("h3",null,"关于本系统课程信息的说明",-1)),(0,a.Lk)("button",{class:"close-btn",onClick:t[6]||(t[6]=e=>i.showHelp=!1)},"×")]),t[13]||(t[13]=(0,a.Fv)('一些说明 本系统中,课程分为两大类:选修课和必修课。 选修课有8个小类:通识选修、人文选修、专业方向、体育、学科基础、暑期国际课、数学与自然科学、重修专栏。人文选修类包括采用“抢选”方式进行选课的所有选修课,以及“改革开放史”和“社会主义发展史”两门人文社会科学类的选修课。 体育课单独作为一类,不属于人文选修类。重修课程的选课归为选修课的“重修专栏”类别,不属于必修课范畴。 重修专栏可以分享任何类别课程 ,但仅限分享重修体验 。
必修课有5个小类:数学与自然科学、人文社会科学、学科基础、专业方向、实践。如上所述,本系统中重修的必修课程也属于选修课范畴。 特别说明:军训课程属于实践类,系辅导员给分,在创建课程时课程教师请填写辅导员。
在创建课程时,请先了解课程的类别,以及课程的开课院系(详见下文) 。如果同一课程的任课教师不同,用户可以创建多个同名课程,例如“A老师-篮球”和“B老师-篮球”将被视为两个不同的课程。 创建的课程卡片需经过管理员审核 ,审核进度可在“我的课程”中实时查看。
如何查看课程类别和开课院系? 1. 本人课程 在教务系统选择“我的考试”,选择对应的学期后,即可查看当前学期的课程类别和开课院系。
2. 非本人课程 在教务系统选择“公共课表查询”,课表类型选择“班级课表”,再选好要查询的学期,并填写要查询的班级名称,点击查询按钮。
进入班级课表后,即可对应课程的开课院系。然后记下老师的姓名。
然后回到公共课表查询页面,课表类型选择“教师课表”,同样选好要查询的学期,并填写要查询的教师姓名,点击查询按钮。
进入教师课表后,找到此课程,即可查看课程类别。
',1))])])):(0,a.Q3)("",!0)])}s(4979);const R={key:0,class:"modal-overlay"},q={class:"modal-content"},B={class:"course-detail"},Q={key:0,class:"share-modal"},J={key:1,class:"error-modal"},H={class:"rating-section"},K={class:"total-rating"},G={class:"progress-container"},Y={class:"stars"},Z=["onMouseover","onClick"],ee={class:"ai-summary"},te={key:0,class:"typing-cursor"},se={class:"comment-section"},oe={class:"sort-options"},ae={key:0,class:"comments-list"},ne={class:"comment-meta"},ie={class:"comment-time",style:{"margin-left":"10px"}},le=["onClick"],re={style:{"margin-top":"8px"}},ce={class:"comment-actions"},ue={style:{color:"red"}},de=["onClick"],he=["onClick"],me={key:1,class:"no-comments"},ge={key:2,class:"chat-modal-overlay"},pe={class:"chat-modal-content"},ke={class:"chat-modal-actions"},ve=["disabled"],be={key:3,class:"chat-modal-overlay"},Ce={class:"chat-modal-content"},fe={class:"chat-modal-actions"},ye={class:"new-comment"};function Le(e,t,s,n,i,l){const r=(0,a.g2)("el-progress");return s.isVisible?((0,a.uX)(),(0,a.CE)("div",R,[(0,a.Lk)("div",q,[(0,a.Lk)("span",{class:"close",onClick:t[0]||(t[0]=(...e)=>l.closeModal&&l.closeModal(...e))},"×"),(0,a.Lk)("div",B,[(0,a.Lk)("h3",null,[(0,a.eW)((0,y.v_)(s.course.course_name)+" ",1),s.course.titles&&s.course.titles.length>0?((0,a.uX)(!0),(0,a.CE)(a.FK,{key:0},(0,a.pI)(s.course.titles,(e=>((0,a.uX)(),(0,a.CE)("span",{key:e.title,class:"course-title",style:(0,y.Tr)({borderColor:e.color,color:e.color})},(0,y.v_)(e.title),5)))),128)):(0,a.Q3)("",!0),(0,a.Lk)("button",{class:"share-btn",onClick:t[1]||(t[1]=(...e)=>l.shareCourse&&l.shareCourse(...e))},"分享给好友")]),(0,a.Lk)("p",null,[t[16]||(t[16]=(0,a.Lk)("strong",null,"分类:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCategoryName(s.course.category_id)),1)]),(0,a.Lk)("p",null,[t[17]||(t[17]=(0,a.Lk)("strong",null,"教师:",-1)),(0,a.eW)(" "+(0,y.v_)(s.course.teachers),1)]),(0,a.Lk)("p",null,[t[18]||(t[18]=(0,a.Lk)("strong",null,"开课院系:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCollegeName(s.course.college)),1)]),i.showShareModal?((0,a.uX)(),(0,a.CE)("div",Q," 链接复制成功,快去分享给其他小伙伴吧! ")):(0,a.Q3)("",!0),i.showErrorModal?((0,a.uX)(),(0,a.CE)("div",J," 获取评论数据失败,正在刷新页面... ")):(0,a.Q3)("",!0),(0,a.Lk)("div",H,[(0,a.Lk)("h4",null,"课程实时平均分 ("+(0,y.v_)(s.course.rating_count)+"人评分)",1),(0,a.Lk)("div",K,(0,y.v_)(i.totalRating),1),(0,a.Lk)("div",G,[(0,a.bF)(r,{class:"progress",percentage:i.fiveStarPercent,status:"success","text-inside":""},{default:(0,a.k6)((()=>[(0,a.eW)("5星: "+(0,y.v_)(i.fiveStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,a.bF)(r,{class:"progress",percentage:i.fourStarPercent,status:"success","text-inside":""},{default:(0,a.k6)((()=>[(0,a.eW)("4星: "+(0,y.v_)(i.fourStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,a.bF)(r,{class:"progress",percentage:i.threeStarPercent,status:"warning","text-inside":""},{default:(0,a.k6)((()=>[(0,a.eW)("3星: "+(0,y.v_)(i.threeStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,a.bF)(r,{class:"progress",percentage:i.twoStarPercent,status:"warning","text-inside":""},{default:(0,a.k6)((()=>[(0,a.eW)("2星: "+(0,y.v_)(i.twoStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"]),(0,a.bF)(r,{class:"progress",percentage:i.oneStarPercent,status:"exception","text-inside":""},{default:(0,a.k6)((()=>[(0,a.eW)("1星: "+(0,y.v_)(i.oneStarPercent.toFixed(2))+"%",1)])),_:1},8,["percentage"])]),(0,a.Lk)("div",Y,[((0,a.uX)(),(0,a.CE)(a.FK,null,(0,a.pI)(5,(e=>(0,a.Lk)("span",{key:e,class:(0,y.C4)({highlighted:e<=i.userRating}),onMouseover:t=>l.highlightStars(e),onMouseout:t[2]||(t[2]=(...e)=>l.resetStars&&l.resetStars(...e)),onClick:t=>l.confirmRating(e)}," ★ ",42,Z))),64))])]),(0,a.Lk)("p",ee,[t[19]||(t[19]=(0,a.Lk)("span",{style:{display:"block","margin-bottom":"-15px"}},[(0,a.Lk)("strong",null,"AI课程总结"),(0,a.Lk)("span",{style:{color:"white","font-size":"8px","margin-left":"5px","border-radius":"4px",padding:"1px 4px","background-color":"red","vertical-align":"super"}},"Beta"),(0,a.Lk)("span",{style:{"font-size":"12px","margin-left":"5px"}},[(0,a.eW)(" 内容由 "),(0,a.Lk)("img",{src:"https://download.东北大学.com/course_system/deepseek.svg",style:{height:"16px","vertical-align":"middle"}}),(0,a.eW)(" DeepSeek V3 生成,仅供参考 ")])],-1)),t[20]||(t[20]=(0,a.Lk)("br",null,null,-1)),i.displayedSummary?((0,a.uX)(),(0,a.CE)(a.FK,{key:0},[(0,a.eW)((0,y.v_)(i.displayedSummary),1),i.isTyping?((0,a.uX)(),(0,a.CE)("span",te,"|")):(0,a.Q3)("",!0)],64)):((0,a.uX)(),(0,a.CE)(a.FK,{key:1},[(0,a.eW)(" 当前课程的评分和评论数据过少,暂不能生成AI总结。 ")],64))])]),(0,a.Lk)("div",se,[(0,a.Lk)("div",oe,[(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"radio",value:"like_count","onUpdate:modelValue":t[3]||(t[3]=e=>i.sortBy=e),onChange:t[4]||(t[4]=(...e)=>l.fetchComments&&l.fetchComments(...e))},null,544),[[o.XL,i.sortBy]]),t[21]||(t[21]=(0,a.eW)(" 赞数最多优先"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"radio",value:"comment_time","onUpdate:modelValue":t[5]||(t[5]=e=>i.sortBy=e),onChange:t[6]||(t[6]=(...e)=>l.fetchComments&&l.fetchComments(...e))},null,544),[[o.XL,i.sortBy]]),t[22]||(t[22]=(0,a.eW)(" 最新评论优先"))])]),l.filteredComments?((0,a.uX)(),(0,a.CE)("div",ae,[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(i.comments,(e=>((0,a.uX)(),(0,a.CE)("div",{key:e.comment_id,class:"comment"},[(0,a.Lk)("div",ne,[(0,a.Lk)("strong",null,(0,y.v_)(e.nickname),1),(0,a.Lk)("span",ie,"发表于 "+(0,y.v_)(l.formatTime(e.comment_time)),1),(0,a.Lk)("span",{class:(0,y.C4)(["like-section",{liked:e.is_liked}]),onClick:t=>l.toggleLike(e)}," ❤ "+(0,y.v_)(e.like_count),11,le)]),(0,a.Lk)("div",re,(0,y.v_)(e.comment_content),1),(0,a.Lk)("div",ce,[(0,a.Lk)("span",null,[t[23]||(t[23]=(0,a.eW)("评分: ")),(0,a.Lk)("strong",ue,(0,y.v_)(e.rating),1)]),e.deleteable?((0,a.uX)(),(0,a.CE)("button",{key:0,onClick:t=>l.deleteComment(e.comment_id),class:"delete-btn"}," 删除 ",8,de)):((0,a.uX)(),(0,a.CE)("button",{key:1,class:"chat-start-btn",onClick:t=>l.openChatModal(e.comment_id)}," 发起聊天 ",8,he))])])))),128))])):((0,a.uX)(),(0,a.CE)("p",me,"本课程暂无评论。")),i.isChatModalVisible?((0,a.uX)(),(0,a.CE)("div",ge,[(0,a.Lk)("div",pe,[(0,a.Lk)("span",{class:"chat-close-btn",onClick:t[7]||(t[7]=(...e)=>l.closeChatModal&&l.closeChatModal(...e))},"×"),t[24]||(t[24]=(0,a.Lk)("h3",null,"发起聊天",-1)),(0,a.bo)((0,a.Lk)("textarea",{"onUpdate:modelValue":t[8]||(t[8]=e=>i.chatMessage=e),placeholder:"请输入聊天内容(至少6个字符)",class:"chat-textarea"},null,512),[[o.Jo,i.chatMessage]]),(0,a.Lk)("div",ke,[(0,a.Lk)("button",{onClick:t[9]||(t[9]=(...e)=>l.submitChat&&l.submitChat(...e)),disabled:i.chatMessage.length<6},"发起",8,ve)])])])):(0,a.Q3)("",!0),i.isConversationExistsModalVisible?((0,a.uX)(),(0,a.CE)("div",be,[(0,a.Lk)("div",Ce,[(0,a.Lk)("span",{class:"chat-close-btn",onClick:t[10]||(t[10]=(...e)=>l.closeConversationExistsModal&&l.closeConversationExistsModal(...e))},"×"),t[25]||(t[25]=(0,a.Lk)("h3",null,"在此课程下,您与此用户已有会话!",-1)),(0,a.Lk)("div",fe,[(0,a.Lk)("button",{onClick:t[11]||(t[11]=e=>l.navigateToConversation(i.existingConversationId))},"进入会话"),(0,a.Lk)("button",{onClick:t[12]||(t[12]=(...e)=>l.closeConversationExistsModal&&l.closeConversationExistsModal(...e))},"取消")])])])):(0,a.Q3)("",!0),(0,a.Lk)("div",ye,[(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[13]||(t[13]=e=>i.nickname=e),placeholder:"一句话概括您的评论,如:被x老师伤透了心"},null,512),[[o.Jo,i.nickname]]),(0,a.bo)((0,a.Lk)("textarea",{"onUpdate:modelValue":t[14]||(t[14]=e=>i.commentContent=e),placeholder:"我们推荐您分享本课程的课程内容、学习难度、考核方式和给分好坏,以帮助更多同学做出判断。支持删除自己的评论。",style:{resize:"none",height:"50px"}},null,512),[[o.Jo,i.commentContent]]),(0,a.Lk)("button",{onClick:t[15]||(t[15]=(...e)=>l.submitComment&&l.submitComment(...e))},"提交评论")])])])])):(0,a.Q3)("",!0)}var _e={props:{isVisible:{type:Boolean,required:!0},course:{type:Object,required:!0}},data(){return{token:null,userRating:0,totalRating:0,fiveStarPercent:0,fourStarPercent:0,threeStarPercent:0,twoStarPercent:0,oneStarPercent:0,comments:[],nickname:"",commentContent:"",sortBy:"like_count",showShareModal:!1,cachedEmail:null,isChatModalVisible:!1,isConversationExistsModalVisible:!1,chatMessage:"",currentCommentId:null,existingConversationId:null,showErrorModal:!1,aiSummary:null,displayedSummary:"",isTyping:!1,shouldStopTyping:!1}},async mounted(){try{this.getToken(),await Promise.all([this.fetchAndCacheEmail(),this.fetchRatingDistribution(),this.fetchUserRating(),this.fetchComments(),this.fetchAISummary()])}catch(e){console.error("Error loading data:",e)}},watch:{async course(e){if(e&&e.course_id){this.aiSummary=null,this.displayedSummary="",this.isTyping=!1,this.getToken();try{await Promise.all([this.fetchRatingDistribution(),this.fetchUserRating(),this.fetchComments(),this.fetchAISummary()])}catch(t){console.error("Error fetching course details:",t)}}},displayedSummary(){this.isTyping&&this.$nextTick((()=>{const e=document.querySelector(".course-detail");e&&(e.scrollTop=e.scrollHeight)}))}},computed:{filteredComments(){return this.comments.length>0?this.comments:null}},methods:{getToken(){const e=document.cookie.split("; ").find((e=>e.startsWith("token=")));e?this.token=e.split("=")[1]:(console.error("Token not found in cookies"),this.token=null)},closeModal(){this.shouldStopTyping=!0,this.isTyping=!1,this.displayedSummary="",this.aiSummary=null,this.$emit("close")},getCategoryName(e){const t={1:"选修课-通识选修类",2:"选修课-人文选修类",3:"选修课-专业方向类",4:"选修课-体育类",5:"选修课-学科基础类",6:"选修课-暑期国际课",7:"选修课-数学与自然科学类",8:"选修课-重修专栏",9:"必修课-数学与自然科学类",10:"必修课-人文社会科学类",11:"必修课-学科基础类",12:"必修课-专业方向类",13:"必修课-实践类"};return t[e]||"未知分类"},async fetchRatingDistribution(){const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-course-ratings-distribution?course_id=${this.course.course_id}`);if(e.ok){const t=await e.json();this.totalRating=t.total_rating||0,this.fiveStarPercent=100*t.five_stars,this.fourStarPercent=100*t.four_stars,this.threeStarPercent=100*t.three_stars,this.twoStarPercent=100*t.two_stars,this.oneStarPercent=100*t.one_star}else 404===e.status&&(this.totalRating=0,this.fiveStarPercent=0,this.fourStarPercent=0,this.threeStarPercent=0,this.twoStarPercent=0,this.oneStarPercent=0)},async fetchUserRating(){const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-user-rating?course_id=${this.course.course_id}`,{headers:{Authorization:this.token}});if(200===e.status){const t=await e.json();this.userRating=t.rating}else this.userRating=0},highlightStars(e){this.userRating=e},resetStars(){this.fetchUserRating()},confirmRating(e){confirm(`您确定要给课程 "${this.course.course_name}" 评分:${e}.0 吗?如您之前有评分记录,此评分将覆盖之前的评分。`)&&this.submitRating(e)},async submitRating(e){const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-rating",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.course.course_id,rating:e})});t.ok&&(this.fetchRatingDistribution(),this.fetchUserRating())},async typewriterEffect(e,t=10){this.isTyping=!0,this.displayedSummary="",this.shouldStopTyping=!1;for(let s=0;ssetTimeout(e,t)))}this.isTyping=!1},async fetchAISummary(){try{const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/ai_summary/summary?course_id=${this.course.course_id}`);if(!e.ok){if(404===e.status)return this.aiSummary=null,void(this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。");throw new Error("获取AI总结失败")}const t=await e.json();t.summary?(this.aiSummary=t.summary,await this.typewriterEffect(this.aiSummary)):this.displayedSummary="当前课程的评分和评论数据过少,暂不能生成AI总结。"}catch(e){console.error("生成AI总结失败:",e),this.displayedSummary="生成AI总结时出错,请稍后再试。"}},async fetchComments(){try{if(!this.token)return this.showErrorModal=!0,void setTimeout((()=>{window.location.reload()}),2e3);const e=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/get-comments?course_id=${this.course.course_id}&sort_by=${this.sortBy}`,{headers:{Authorization:this.token}});if(403===e.status)return this.showErrorModal=!0,void setTimeout((()=>{window.location.reload()}),2e3);if(404===e.status)return void(this.comments=[]);if(!e.ok)throw new Error("获取评论失败");const t=await e.json();this.comments=t.comments}catch(e){console.error("获取评论失败:",e),this.showErrorModal=!0,setTimeout((()=>{window.location.reload()}),2e3)}},async toggleLike(e){e.is_liked?await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/unlike-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e.comment_id})}):await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/like-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e.comment_id})}),this.fetchComments()},async submitComment(){this.nickname.length<3||this.commentContent.length<6?alert("您的昵称请至少包含3个字符,评论请至少包含6个字符。"):(await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/submit-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({course_id:this.course.course_id,nickname:this.nickname,comment_content:this.commentContent})}),this.fetchComments(),this.nickname="",this.commentContent="")},formatTime(e){const t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0"),n=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${s}-${o}-${a} ${n}:${i}`},async fetchAndCacheEmail(){if(!this.cachedEmail)if(this.token)try{const e=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/verifyToken",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token}}),t=await e.json();e.ok&&t.email?this.cachedEmail=t.email:console.error("JWT验证失败或未找到邮箱")}catch(e){console.error("JWT验证时出错:",e)}else console.error("未找到JWT信息")},getUserEmailFromCookie(){return this.cachedEmail?this.cachedEmail:(console.error("邮箱尚未缓存"),"")},base64Encode(e){return btoa(e)},shareCourse(){const e=this.course.course_name,t=this.base64Encode(this.course.course_id.toString());let s="";s=0!==this.totalRating?`我在NEU小站为课程【${e}】评分,当前评分【${this.totalRating}】,点击【https://course.xn--xhq44jb2fzpc.com/courses?c=${t}】加入评分吧!`:`我在NEU小站为课程【${e}】评分,点击【https://course.xn--xhq44jb2fzpc.com/courses?c=${t}】加入评分吧!`,this.copyToClipboard(s),this.showShareModal=!0,setTimeout((()=>{this.showShareModal=!1}),3e3)},copyToClipboard(e){const t=document.createElement("textarea");t.value=e,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t)},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"},openChatModal(e){this.currentCommentId=e,this.chatMessage="",this.isChatModalVisible=!0},closeChatModal(){this.isChatModalVisible=!1},closeConversationExistsModal(){this.isConversationExistsModalVisible=!1},async submitChat(){if(this.chatMessage.length<6)alert("聊天内容需至少6个字符");else try{const e=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/chat/start-conversation",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:this.currentCommentId,content:this.chatMessage})}),t=await e.json();e.ok&&"Conversation started successfully"===t.message?this.$router.push(`/chat?mid=${t.conversation_id}`):e.ok&&"Conversation already exists"===t.message?(this.existingConversationId=t.conversation_id,this.isConversationExistsModalVisible=!0):"Recipient account status is abnormal, cannot create a conversation"===t.error?alert("此账号状态异常,暂时无法发起聊天!"):"Cannot start a conversation with yourself!"===t.error?alert("不能向自己发起聊天!"):alert("发起会话失败,请稍后再试")}catch(e){console.error("Error starting conversation:",e),alert("发起会话失败,请稍后再试")}finally{this.closeChatModal()}},navigateToConversation(e){this.$router.push(`/chat?mid=${e}`),this.closeConversationExistsModal()},async deleteComment(e){const t=confirm("确定删除评论吗?");if(t)try{const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/delete-comment",{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.token},body:JSON.stringify({comment_id:e})});if(t.ok)this.fetchComments();else{const e=await t.json();alert(e.error||"删除评论失败")}}catch(s){console.error("删除评论出错:",s),alert("删除评论失败")}}}};const we=(0,m.A)(_e,[["render",Le],["__scopeId","data-v-5bb6a1dc"]]);var Ee=we,xe={components:{CourseDetailModal:Ee},data(){return{submissions:[],newCourseName:"",newCategoryId:"",newTeachers:"",newCollege:"",currentPage:1,itemsPerPage:10,totalPages:1,isLoaded:!1,selectedCourse:null,showDetail:!1,cachedEmail:null,collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"},showHelp:!1}},computed:{paginatedSubmissions(){const e=(this.currentPage-1)*this.itemsPerPage,t=e+this.itemsPerPage;return this.submissions.slice(e,t)},filteredColleges(){return Object.fromEntries(Object.entries(this.collegeMap).filter((([e])=>"59"!==e)))}},mounted(){setTimeout((async()=>{this.isLoaded=!0,this.fetchSubmissions()}),300),"true"===this.$route.query.m&&(this.showHelp=!0);const e=this.$route.query.c;if(e)try{const t=atob(e);this.isPositiveInteger(t)&&(this.decodedParam=t,this.isValid=!0,this.loadCourseDetail(this.decodedParam))}catch(t){}},methods:{isPositiveInteger(e){const t=Number(e);return Number.isInteger(t)&&t>0},async fetchAndCacheEmail(){if(this.cachedEmail)return;const e=document.cookie.split("; "),t=e.find((e=>e.startsWith("token="))),s=t?t.split("=")[1]:"";if(s)try{const e=await fetch("https://userlogin.xn--xhq44jb2fzpc.com/verifyToken",{method:"POST",headers:{"Content-Type":"application/json",Authorization:s}}),t=await e.json();e.ok&&t.email?this.cachedEmail=t.email:console.error("JWT验证失败或未找到邮箱")}catch(o){console.error("JWT验证时出错:",o)}else console.error("未找到JWT信息")},async fetchSubmissions(){const e=this.getCookie("token");if(!e)return void alert("无法获取JWT,请重新登录。");const t=await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/user/user-submissions",{method:"GET",headers:{"Content-Type":"application/json",Authorization:e}}),s=await t.json();200===t.status?(this.submissions=s,this.totalPages=Math.ceil(this.submissions.length/this.itemsPerPage)):alert(s.error||"查询投稿记录失败")},getCookie(e){const t=document.cookie.split(";");for(let s of t){const[t,o]=s.trim().split("=");if(t===e)return o}return null},goToPage(e){this.currentPage=e},async submitCourse(){if(this.newCourseName&&this.newCategoryId&&this.newTeachers&&this.newCollege){if(confirm("确认提交审核吗?")){const e=this.getCookie("token");if(!e)return void alert("无法获取JWT,请重新登录。");const t={course_name:this.newCourseName,category_id:this.newCategoryId,teachers:this.newTeachers,college:this.newCollege};await fetch("https://coursesystem.xn--xhq44jb2fzpc.com/user/submit-course",{method:"POST",headers:{"Content-Type":"application/json",Authorization:e},body:JSON.stringify(t)}),this.newCourseName="",this.newCategoryId="",this.newTeachers="",this.newCollege="",this.fetchSubmissions()}}else alert("请填写所有字段后提交!")},getCategoryName(e){const t={1:"选修课-通识选修类",2:"选修课-人文选修类",3:"选修课-专业方向类",4:"选修课-体育类",5:"选修课-学科基础类",6:"选修课-暑期国际课",7:"选修课-数学与自然科学类",8:"选修课-重修专栏",9:"必修课-数学与自然科学类",10:"必修课-人文社会科学类",11:"必修课-学科基础类",12:"必修课-专业方向类",13:"必修课-实践类"};return t[e]||"未知分类"},formatTime(e){const t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0"),n=String(t.getHours()).padStart(2,"0"),i=String(t.getMinutes()).padStart(2,"0");return`${s}-${o}-${a} ${n}:${i}`},async loadCourseDetail(e){try{const t=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${e}`),s=await t.json();this.selectedCourse=s,this.showDetail=!0}catch(t){console.error("Error loading course details:",t)}},closeCourseDetail(){this.showDetail=!1,this.selectedCourse=null},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"}}};const Se=(0,m.A)(xe,[["render",O],["__scopeId","data-v-72ba6bf4"]]);var Pe=Se;const Te={key:0,class:"rating-page"},Me={class:"search-sort-bar"},We={class:"category-checkboxes"},Xe=["value"],Ie={class:"course-cards"},je=["onClick"],De={class:"card-type"},Ae={class:"card-teachers"},Fe={class:"card-college"},Ne={class:"card-ratecount"},Ue={key:0,class:"card-topcomment"},$e={key:1,class:"card-topcomment"},ze={class:"card-rate"},Ve={class:"pagination-bar"},Oe=["onClick"],Re=["disabled"],qe={key:1};function Be(e,t,s,n,i,l){const r=(0,a.g2)("CourseDetailModal");return i.isLoaded?((0,a.uX)(),(0,a.CE)("div",Te,[t[30]||(t[30]=(0,a.Lk)("h2",{class:"rating-note"},"每页最多展示12个课程,一次最多展示10个页码。点击星星进行评分,星星记录的是您的历史评分。",-1)),(0,a.Lk)("div",Me,[(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[0]||(t[0]=e=>i.searchQuery=e),type:"text",placeholder:"请输入课程名"},null,512),[[o.Jo,i.searchQuery]]),(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[1]||(t[1]=e=>i.teacherQuery=e),type:"text",style:{width:"450px"},placeholder:"请输入教师名,多个教师以英文逗号分隔,如'张三,李四'"},null,512),[[o.Jo,i.teacherQuery]]),(0,a.Lk)("div",We,[(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[2]||(t[2]=e=>i.selectedCategories=e),value:"1"},null,512),[[o.lH,i.selectedCategories]]),t[15]||(t[15]=(0,a.eW)(" 通识选修类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[3]||(t[3]=e=>i.selectedCategories=e),value:"2"},null,512),[[o.lH,i.selectedCategories]]),t[16]||(t[16]=(0,a.eW)(" 人文选修类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[4]||(t[4]=e=>i.selectedCategories=e),value:"3"},null,512),[[o.lH,i.selectedCategories]]),t[17]||(t[17]=(0,a.eW)(" 专业方向类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[5]||(t[5]=e=>i.selectedCategories=e),value:"4"},null,512),[[o.lH,i.selectedCategories]]),t[18]||(t[18]=(0,a.eW)(" 体育类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[6]||(t[6]=e=>i.selectedCategories=e),value:"5"},null,512),[[o.lH,i.selectedCategories]]),t[19]||(t[19]=(0,a.eW)(" 学科基础类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[7]||(t[7]=e=>i.selectedCategories=e),value:"6"},null,512),[[o.lH,i.selectedCategories]]),t[20]||(t[20]=(0,a.eW)(" 暑期国际课"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[8]||(t[8]=e=>i.selectedCategories=e),value:"7"},null,512),[[o.lH,i.selectedCategories]]),t[21]||(t[21]=(0,a.eW)(" 数学与自然科学类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[9]||(t[9]=e=>i.selectedCategories=e),value:"8"},null,512),[[o.lH,i.selectedCategories]]),t[22]||(t[22]=(0,a.eW)(" 重修专栏"))])]),(0,a.bo)((0,a.Lk)("select",{"onUpdate:modelValue":t[10]||(t[10]=e=>i.sortBy=e)},t[23]||(t[23]=[(0,a.Lk)("option",{value:"rating"},"评分由高到低",-1),(0,a.Lk)("option",{value:"rating-asc"},"评分由低到高",-1),(0,a.Lk)("option",{value:"rating_count"},"评分人数由多到少",-1)]),512),[[o.u1,i.sortBy]]),(0,a.bo)((0,a.Lk)("select",{"onUpdate:modelValue":t[11]||(t[11]=e=>i.selectedCollege=e)},[t[24]||(t[24]=(0,a.Lk)("option",{value:""},"不限院系",-1)),((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.filteredColleges,(([e,t])=>((0,a.uX)(),(0,a.CE)("option",{key:e,value:e},(0,y.v_)(t),9,Xe)))),128))],512),[[o.u1,i.selectedCollege]]),(0,a.Lk)("button",{onClick:t[12]||(t[12]=(...e)=>l.searchCourses&&l.searchCourses(...e))},"更新查询")]),(0,a.Lk)("div",Ie,[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(i.courses,(e=>((0,a.uX)(),(0,a.CE)("div",{key:e.course_id,class:"course-card",onClick:t=>l.showCourseDetail(e)},[(0,a.Lk)("h3",null,[(0,a.eW)((0,y.v_)(e.course_name)+" ",1),e.titles&&e.titles.length>0?((0,a.uX)(!0),(0,a.CE)(a.FK,{key:0},(0,a.pI)(e.titles,(e=>((0,a.uX)(),(0,a.CE)("span",{key:e.title,class:"course-title",style:(0,y.Tr)({borderColor:e.color,color:e.color})},(0,y.v_)(e.title),5)))),128)):(0,a.Q3)("",!0)]),(0,a.Lk)("p",De,[t[25]||(t[25]=(0,a.Lk)("strong",null,"分类:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCategoryName(e.category_id)),1)]),(0,a.Lk)("p",Ae,[t[26]||(t[26]=(0,a.Lk)("strong",null,"教师:",-1)),(0,a.eW)(" "+(0,y.v_)(e.teachers),1)]),(0,a.Lk)("p",Fe,[t[27]||(t[27]=(0,a.Lk)("strong",null,"开课院系:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCollegeName(e.college)),1)]),(0,a.Lk)("p",Ne,[t[28]||(t[28]=(0,a.Lk)("strong",null,"评分人数:",-1)),(0,a.eW)(" "+(0,y.v_)(e.rating_count),1)]),e.top_comment?((0,a.uX)(),(0,a.CE)("p",Ue,'"'+(0,y.v_)(l.formatTopComment(e.top_comment))+'"',1)):((0,a.uX)(),(0,a.CE)("p",$e,"暂无评论")),(0,a.Lk)("p",ze,[(0,a.eW)((0,y.v_)(e.rating),1),t[29]||(t[29]=(0,a.Lk)("span",{class:"unit"}," 分",-1))])],8,je)))),128))]),(0,a.Lk)("div",Ve,[(0,a.Lk)("button",{onClick:t[13]||(t[13]=e=>l.goToPage(1)),class:(0,y.C4)({active:1===i.currentPage})},"首页",2),((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.getPaginationPages(),(e=>((0,a.uX)(),(0,a.CE)("button",{key:e,onClick:t=>l.goToPage(e),class:(0,y.C4)({active:i.currentPage===e})},(0,y.v_)(e),11,Oe)))),128)),(0,a.Lk)("button",{onClick:t[14]||(t[14]=e=>l.goToPage(i.totalPages)),class:(0,y.C4)({active:i.currentPage===i.totalPages}),disabled:0===i.totalPages}," 尾页 ",10,Re)]),i.selectedCourse?((0,a.uX)(),(0,a.Wv)(r,{key:0,isVisible:i.showDetail,course:i.selectedCourse,onClose:l.closeCourseDetail},null,8,["isVisible","course","onClose"])):(0,a.Q3)("",!0)])):((0,a.uX)(),(0,a.CE)("div",qe,t[31]||(t[31]=[(0,a.Lk)("p",{style:{color:"#666"}},"加载中,请稍后...",-1)])))}var Qe={components:{CourseDetailModal:Ee},data(){return{searchQuery:"",teacherQuery:"",sortBy:"rating",sortOrder:"desc",selectedCategories:[],courses:[],currentPage:1,totalPages:1,showDetail:!1,selectedCourse:null,courseComments:[],isLoaded:!1,selectedCollege:"",allColleges:[],collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"}}},computed:{filteredColleges(){return Object.entries(this.collegeMap).filter((([e])=>"59"!==e))}},mounted(){setTimeout((()=>{this.isLoaded=!0,this.searchCourses()}),300),this.allColleges=Object.keys(this.collegeMap).map(Number)},methods:{async fetchCourses(){let e="rating-asc"===this.sortBy?"rating":this.sortBy;this.sortOrder="rating-asc"===this.sortBy?"asc":"desc";const t=0===this.selectedCategories.length?"1,2,3,4,5,6,7,8":this.selectedCategories.join(","),s=this.selectedCollege?`&college=${this.selectedCollege}`:"",o=encodeURIComponent(this.searchQuery),a=encodeURIComponent(this.teacherQuery),n=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/list/courses?search=${o}&teacher=${a}&sortBy=${e}&sort=${this.sortOrder}&category=${t}${s}&page=${this.currentPage}`),i=await n.json();this.courses=i.courses,this.currentPage=i.currentPage,this.totalPages=i.totalPages},getPaginationPages(){const e=[],t=this.totalPages,s=this.currentPage,o=10;if(t<=o)for(let a=1;a<=t;a++)e.push(a);else{let o=Math.max(s-5,1),a=Math.min(s+4,t);s<=6&&(o=1,a=10),s>=t-4&&(o=t-9,a=t);for(let t=o;t<=a;t++)e.push(t)}return e},searchCourses(){this.currentPage=1,this.fetchCourses()},goToPage(e){e<1||e>this.totalPages||(this.currentPage=e,this.fetchCourses())},showCourseDetail(e){this.selectedCourse={...e},this.showDetail=!0},formatTopComment(e){if(!e)return"";let t=0,s="";for(let o=0;o255?1:.5;if(t+a>29)return s+"...";t+=a,s+=e[o]}return s},closeCourseDetail(){this.showDetail=!1,this.selectedCourse=null},getCategoryName(e){const t={1:"通识选修类",2:"人文选修类",3:"专业方向类",4:"体育类",5:"学科基础类",6:"暑期国际课",7:"数学与自然科学类",8:"重修专栏"};return t[e]||"未知分类"},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"}}};const Je=(0,m.A)(Qe,[["render",Be],["__scopeId","data-v-7aa9d5ae"]]);var He=Je;const Ke={key:0,class:"rating-page"},Ge={class:"search-sort-bar"},Ye={class:"category-checkboxes"},Ze={class:"select-container"},et=["value"],tt={class:"course-cards"},st=["onClick"],ot={class:"card-type"},at={class:"card-teachers"},nt={class:"card-college"},it={class:"card-ratecount"},lt={key:0,class:"card-topcomment"},rt={key:1,class:"card-topcomment"},ct={class:"card-rate"},ut={class:"pagination-bar"},dt=["onClick"],ht=["disabled"],mt={key:1};function gt(e,t,s,n,i,l){const r=(0,a.g2)("CourseDetailModal");return i.isLoaded?((0,a.uX)(),(0,a.CE)("div",Ke,[t[24]||(t[24]=(0,a.Lk)("h2",{class:"rating-note"},"每页最多展示12个课程,一次最多展示10个页码。点击星星进行评分,星星记录的是您的历史评分。",-1)),(0,a.Lk)("div",Ge,[(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[0]||(t[0]=e=>i.searchQuery=e),type:"text",placeholder:"请输入课程名"},null,512),[[o.Jo,i.searchQuery]]),(0,a.bo)((0,a.Lk)("input",{"onUpdate:modelValue":t[1]||(t[1]=e=>i.teacherQuery=e),type:"text",style:{width:"450px"},placeholder:"请输入教师名,多个教师以英文逗号分隔,如'张三,李四'"},null,512),[[o.Jo,i.teacherQuery]]),(0,a.Lk)("div",Ye,[(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[2]||(t[2]=e=>i.selectedCategories=e),value:"9"},null,512),[[o.lH,i.selectedCategories]]),t[12]||(t[12]=(0,a.eW)(" 数学与自然科学类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[3]||(t[3]=e=>i.selectedCategories=e),value:"10"},null,512),[[o.lH,i.selectedCategories]]),t[13]||(t[13]=(0,a.eW)(" 人文社会科学类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[4]||(t[4]=e=>i.selectedCategories=e),value:"11"},null,512),[[o.lH,i.selectedCategories]]),t[14]||(t[14]=(0,a.eW)(" 学科基础类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[5]||(t[5]=e=>i.selectedCategories=e),value:"12"},null,512),[[o.lH,i.selectedCategories]]),t[15]||(t[15]=(0,a.eW)(" 专业方向类"))]),(0,a.Lk)("label",null,[(0,a.bo)((0,a.Lk)("input",{type:"checkbox","onUpdate:modelValue":t[6]||(t[6]=e=>i.selectedCategories=e),value:"13"},null,512),[[o.lH,i.selectedCategories]]),t[16]||(t[16]=(0,a.eW)(" 实践类"))])]),(0,a.Lk)("div",Ze,[(0,a.bo)((0,a.Lk)("select",{class:"sortBySelect","onUpdate:modelValue":t[7]||(t[7]=e=>i.sortBy=e)},t[17]||(t[17]=[(0,a.Lk)("option",{value:"rating"},"评分由高到低",-1),(0,a.Lk)("option",{value:"rating-asc"},"评分由低到高",-1),(0,a.Lk)("option",{value:"rating_count"},"评分人数由多到少",-1)]),512),[[o.u1,i.sortBy]]),(0,a.bo)((0,a.Lk)("select",{"onUpdate:modelValue":t[8]||(t[8]=e=>i.selectedCollege=e)},[t[18]||(t[18]=(0,a.Lk)("option",{value:""},"不限院系",-1)),((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.filteredColleges,(([e,t])=>((0,a.uX)(),(0,a.CE)("option",{key:e,value:e},(0,y.v_)(t),9,et)))),128))],512),[[o.u1,i.selectedCollege]])]),(0,a.Lk)("button",{onClick:t[9]||(t[9]=(...e)=>l.searchCourses&&l.searchCourses(...e))},"更新查询")]),(0,a.Lk)("div",tt,[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(i.courses,(e=>((0,a.uX)(),(0,a.CE)("div",{key:e.course_id,class:"course-card",onClick:t=>l.showCourseDetail(e)},[(0,a.Lk)("h3",null,[(0,a.eW)((0,y.v_)(e.course_name)+" ",1),e.titles&&e.titles.length>0?((0,a.uX)(!0),(0,a.CE)(a.FK,{key:0},(0,a.pI)(e.titles,(e=>((0,a.uX)(),(0,a.CE)("span",{key:e.title,class:"course-title",style:(0,y.Tr)({borderColor:e.color,color:e.color})},(0,y.v_)(e.title),5)))),128)):(0,a.Q3)("",!0)]),(0,a.Lk)("p",ot,[t[19]||(t[19]=(0,a.Lk)("strong",null,"分类:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCategoryName(e.category_id)),1)]),(0,a.Lk)("p",at,[t[20]||(t[20]=(0,a.Lk)("strong",null,"教师:",-1)),(0,a.eW)(" "+(0,y.v_)(e.teachers),1)]),(0,a.Lk)("p",nt,[t[21]||(t[21]=(0,a.Lk)("strong",null,"开课院系:",-1)),(0,a.eW)(" "+(0,y.v_)(l.getCollegeName(e.college)),1)]),(0,a.Lk)("p",it,[t[22]||(t[22]=(0,a.Lk)("strong",null,"评分人数:",-1)),(0,a.eW)(" "+(0,y.v_)(e.rating_count),1)]),e.top_comment?((0,a.uX)(),(0,a.CE)("p",lt,'"'+(0,y.v_)(l.formatTopComment(e.top_comment))+'"',1)):((0,a.uX)(),(0,a.CE)("p",rt,"暂无评论")),(0,a.Lk)("p",ct,[(0,a.eW)((0,y.v_)(e.rating),1),t[23]||(t[23]=(0,a.Lk)("span",{class:"unit"}," 分",-1))])],8,st)))),128))]),(0,a.Lk)("div",ut,[(0,a.Lk)("button",{onClick:t[10]||(t[10]=e=>l.goToPage(1)),class:(0,y.C4)({active:1===i.currentPage})},"首页",2),((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(l.getPaginationPages(),(e=>((0,a.uX)(),(0,a.CE)("button",{key:e,onClick:t=>l.goToPage(e),class:(0,y.C4)({active:i.currentPage===e})},(0,y.v_)(e),11,dt)))),128)),(0,a.Lk)("button",{onClick:t[11]||(t[11]=e=>l.goToPage(i.totalPages)),class:(0,y.C4)({active:i.currentPage===i.totalPages}),disabled:0===i.totalPages}," 尾页 ",10,ht)]),i.selectedCourse?((0,a.uX)(),(0,a.Wv)(r,{key:0,isVisible:i.showDetail,course:i.selectedCourse,onClose:l.closeCourseDetail},null,8,["isVisible","course","onClose"])):(0,a.Q3)("",!0)])):((0,a.uX)(),(0,a.CE)("div",mt,t[25]||(t[25]=[(0,a.Lk)("p",{style:{color:"#666"}},"加载中,请稍后...",-1)])))}var pt={components:{CourseDetailModal:Ee},data(){return{searchQuery:"",teacherQuery:"",sortBy:"rating",sortOrder:"desc",selectedCategories:[],courses:[],currentPage:1,totalPages:1,showDetail:!1,selectedCourse:null,courseComments:[],isLoaded:!1,selectedCollege:"",allColleges:[],collegeMap:{59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"}}},computed:{filteredColleges(){return Object.entries(this.collegeMap).filter((([e])=>"59"!==e))}},mounted(){setTimeout((()=>{this.isLoaded=!0,this.searchCourses()}),300),this.allColleges=Object.keys(this.collegeMap).map(Number)},methods:{async fetchCourses(){let e="rating-asc"===this.sortBy?"rating":this.sortBy;this.sortOrder="rating-asc"===this.sortBy?"asc":"desc";const t=0===this.selectedCategories.length?"9,10,11,12,13":this.selectedCategories.join(","),s=this.selectedCollege?`&college=${this.selectedCollege}`:"",o=encodeURIComponent(this.searchQuery),a=encodeURIComponent(this.teacherQuery),n=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/list/courses?search=${o}&teacher=${a}&sortBy=${e}&sort=${this.sortOrder}&category=${t}${s}&page=${this.currentPage}`),i=await n.json();this.courses=i.courses,this.currentPage=i.currentPage,this.totalPages=i.totalPages},getPaginationPages(){const e=[],t=this.totalPages,s=this.currentPage,o=10;if(t<=o)for(let a=1;a<=t;a++)e.push(a);else{let o=Math.max(s-5,1),a=Math.min(s+4,t);s<=6&&(o=1,a=10),s>=t-4&&(o=t-9,a=t);for(let t=o;t<=a;t++)e.push(t)}return e},searchCourses(){this.currentPage=1,this.fetchCourses()},goToPage(e){e<1||e>this.totalPages||(this.currentPage=e,this.fetchCourses())},showCourseDetail(e){this.selectedCourse={...e},this.showDetail=!0},formatTopComment(e){if(!e)return"";let t=0,s="";for(let o=0;o255?1:.5;if(t+a>29)return s+"...";t+=a,s+=e[o]}return s},closeCourseDetail(){this.showDetail=!1,this.selectedCourse=null},getCategoryName(e){const t={9:"数学与自然科学类",10:"人文社会科学类",11:"学科基础类",12:"专业方向类",13:"实践类"};return t[e]||"未知分类"},getCollegeName(e){const t={59:"未填写",1:"材料科学与工程学院",2:"创新创业学院",3:"档案馆",4:"党委宣传部",5:"党委组织部",6:"发展规划与学科建设处",7:"佛山研究生创新学院",8:"工程训练中心",9:"工会",10:"工商管理学院",11:"国防教育学院",12:"国际教育学院",13:"后勤服务中心",14:"后勤管理处",15:"浑南管委会",16:"江河建筑学院",17:"尖子班",18:"教务处",19:"基础学院",20:"计划财经处",21:"机器人科学与工程学院",22:"计算机科学与工程学院",23:"计算中心",24:"纪委",25:"机械工程与自动化学院",26:"继续教育学院",27:"科技产业集团",28:"科学技术研究院",29:"理学院",30:"马克思主义学院",31:"民族教育学院",33:"人事处",34:"人文选修课群",35:"软件学院",36:"生命科学与健康学院",37:"体育部",38:"体育场馆管理中心",39:"团委",40:"图书馆",41:"外国语学院",42:"外联处",43:"网络教育学院",44:"未来技术学院",45:"文法学院",46:"校长办公室",47:"信息科学与工程学院",48:"新知识课群",49:"学生处",50:"学生创新中心",51:"学生指导服务中心",52:"研究生院",53:"冶金学院",54:"艺术学院",55:"医学与生物信息工程学院",56:"医院",57:"资产与实验室管理处",58:"资源与土木工程学院"};return t[e]||"未知院系"}}};const kt=(0,m.A)(pt,[["render",gt],["__scopeId","data-v-57f802ca"]]);var vt=kt;const bt={class:"chat-page"},Ct={class:"sidebar"},ft={class:"header"},yt={class:"status-text"},Lt={key:0,class:"no-conversations"},_t=["onClick"],wt={class:"conversation-name"},Et={key:0,class:"new-message-label"},xt={class:"conversation-updated-at"},St={class:"conversation-last-message"},Pt={class:"chat-container"},Tt={class:"conversation-info"},Mt={class:"message-bubble"},Wt={key:0},Xt={class:"input-container"};function It(e,t,s,o,n,i){const l=(0,a.g2)("el-scrollbar"),r=(0,a.g2)("el-button"),c=(0,a.g2)("el-input"),u=(0,a.g2)("el-tooltip"),d=(0,a.g2)("CourseDetailModal");return(0,a.uX)(),(0,a.CE)("div",bt,[(0,a.Lk)("div",Ct,[(0,a.Lk)("h3",ft,[t[2]||(t[2]=(0,a.eW)(" 会话列表 ")),(0,a.Lk)("span",{class:(0,y.C4)(["connection-status",{connected:n.isConnected,disconnected:!n.isConnected}])},[(0,a.Lk)("span",{class:(0,y.C4)(["status-indicator",{connected:n.isConnected,disconnected:!n.isConnected}])},null,2),(0,a.Lk)("span",yt,(0,y.v_)(n.isConnected?"即时聊天已连接":"即时聊天已断开,正在重新连接..."),1)],2)]),(0,a.bF)(l,null,{default:(0,a.k6)((()=>[0===n.conversations.length?((0,a.uX)(),(0,a.CE)("div",Lt," 还没有会话,快去通过评论发起聊天吧! ")):((0,a.uX)(!0),(0,a.CE)(a.FK,{key:1},(0,a.pI)(n.conversations,(e=>((0,a.uX)(),(0,a.CE)("div",{key:e.conversation_id,class:(0,y.C4)(["conversation-item",e.conversation_id===n.activeConversation?"active":""]),onClick:t=>i.selectConversation(e.conversation_id)},[(0,a.Lk)("div",wt,[(0,a.eW)((0,y.v_)(e.course_name)+" ",1),(0,a.Lk)("span",{class:(0,y.C4)(["role-label",{owner:"owner"===e.role,member:"member"===e.role}])},(0,y.v_)("owner"===e.role?"我发起的":"我收到的"),3),e.is_read?(0,a.Q3)("",!0):((0,a.uX)(),(0,a.CE)("span",Et,"新消息"))]),(0,a.Lk)("small",xt,"更新时间: "+(0,y.v_)(i.formatDate(e.updated_at)),1),t[3]||(t[3]=(0,a.Lk)("br",null,null,-1)),(0,a.Lk)("small",St,(0,y.v_)(e.latest_sender?"我:":"对方:")+(0,y.v_)(e.content||"还没有消息哦,快去通过某条课程评论发起聊天吧!"),1)],10,_t)))),128))])),_:1})]),(0,a.Lk)("div",Pt,[(0,a.Lk)("div",Tt,[(0,a.Lk)("span",null,(0,y.v_)(null!==n.rating?"该用户对课程评分为 "+n.rating.toFixed(1):"该用户暂未对课程进行评分"),1),(0,a.bF)(r,{onClick:t[0]||(t[0]=e=>n.selectedCourseId&&i.loadCourseDetail(n.selectedCourseId))},{default:(0,a.k6)((()=>t[4]||(t[4]=[(0,a.eW)("查看课程")]))),_:1})]),(0,a.bF)(l,{ref:"messageScrollbar",class:"message-list"},{default:(0,a.k6)((()=>[((0,a.uX)(!0),(0,a.CE)(a.FK,null,(0,a.pI)(n.messages,((e,t)=>((0,a.uX)(),(0,a.CE)("div",{key:t,class:(0,y.C4)(["message",1===e.sender?"self":"other"])},[(0,a.Lk)("div",Mt,[(0,a.Lk)("span",null,(0,y.v_)(e.content),1),(0,a.Lk)("div",{class:(0,y.C4)(["message-info",1===e.sender?"align-right":"align-left"])},[(0,a.Lk)("small",null,(0,y.v_)(i.formatDate(e.created_at)),1),1===e.sender?((0,a.uX)(),(0,a.CE)("small",Wt,(0,y.v_)(e.is_read?"已读":"未读"),1)):(0,a.Q3)("",!0)],2)])],2)))),128))])),_:1},512),(0,a.Lk)("div",Xt,[(0,a.bF)(c,{modelValue:n.newMessage,"onUpdate:modelValue":t[1]||(t[1]=e=>n.newMessage=e),type:"textarea",rows:"2",placeholder:"请输入您的消息,按Enter换行,Ctrl+Enter发送。",class:"locked-input",onKeydown:i.handleKeyDown},null,8,["modelValue","onKeydown"]),(0,a.bF)(u,{content:"Ctrl + Enter",placement:"top"},{default:(0,a.k6)((()=>[(0,a.bF)(r,{onClick:i.sendMessage,type:"primary"},{default:(0,a.k6)((()=>t[5]||(t[5]=[(0,a.eW)("发送")]))),_:1},8,["onClick"])])),_:1})])]),n.selectedCourse?((0,a.uX)(),(0,a.Wv)(d,{key:0,isVisible:n.showDetail,course:n.selectedCourse,onClose:i.closeCourseDetail},null,8,["isVisible","course","onClose"])):(0,a.Q3)("",!0)])}var jt=s(4373),Dt={components:{CourseDetailModal:Ee},data(){return{userId:"",activeConversation:null,conversations:[],messages:[],newMessage:"",socket:null,rating:null,selectedCourse:null,selectedCourseId:0,showDetail:!1,isConnected:!1}},async activated(){await this.fetchConversations(),this.activeConversation&&await this.selectConversation(this.activeConversation)},async mounted(){try{const e=this.getCookie("token");if(!e)throw new Error("JWT not found in cookies");const t=JSON.parse(atob(e.split(".")[1]));this.userId=t.id,await this.fetchConversations(),this.checkAndSwitchConversation(),this.initializeWebSocket()}catch(e){console.error("Failed to initialize chat page:",e.message)}},beforeUnmount(){this.socket&&this.socket.close()},methods:{async fetchConversations(){try{const e=await jt.A.get("/chat/conversations",{headers:{Authorization:this.getCookie("token")}});this.conversations=[...e.data.conversations]}catch(e){console.error("Failed to fetch conversations:",e)}},formatDate(e){const t=new Date(e);return t.toLocaleString()},async loadCourseDetail(e){try{const t=await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${e}`),s=await t.json();this.selectedCourse=s,this.showDetail=!0}catch(t){console.error("Error loading course details:",t)}},closeCourseDetail(){this.showDetail=!1,this.selectedCourse=null},initializeWebSocket(){const e=this.getCookie("token");if(!e)return void console.error("WebSocket initialization failed: No token found");const t=`${"https:"===window.location.protocol?"wss://coursesystem.xn--xhq44jb2fzpc.com":"ws://49.232.202.164:8080"}/chat?token=${e}`;console.log(`Attempting to connect to WebSocket at: ${t}`),this.socket=new WebSocket(t),this.socket.onopen=()=>{this.isConnected=!0,console.log("WebSocket connected")},this.socket.onmessage=async e=>{try{const t=JSON.parse(e.data);switch(console.log("Received WebSocket message:",t),t.type){case"new_conversation":await this.fetchConversations(),t.conversation_id===this.activeConversation&&await this.selectConversation(t.conversation_id);break;case"new_message":await this.fetchConversations(),t.conversation_id===this.activeConversation&&await this.selectConversation(t.conversation_id);break;case"message_read":if(t.conversation_id===this.activeConversation){const e=this.messages.findIndex((e=>e.message_id===t.message_id&&1===e.sender));-1!==e&&this.$set(this.messages[e],"is_read",!0)}break;case"conversation_read":t.conversation_id===this.activeConversation&&this.messages.forEach((e=>{1===e.sender&&t.message_ids.includes(e.message_id)&&(e.is_read=!0)}));break;default:console.warn(`Unknown WebSocket message type: ${t.type}`)}}catch(t){console.error("Error processing WebSocket message:",t)}},this.socket.onclose=e=>{this.isConnected=!1,console.warn(`WebSocket disconnected: Code ${e.code}, Reason: ${e.reason}`),this.reconnectWebSocket()},this.socket.onerror=e=>{console.error("WebSocket error:",e)}},reconnectWebSocket(){console.warn("Attempting to reconnect WebSocket..."),setTimeout((async()=>{try{this.initializeWebSocket();const e=new Promise(((e,t)=>{const s=setInterval((()=>{this.socket&&this.socket.readyState===WebSocket.OPEN&&(clearInterval(s),e())}),500);setTimeout((()=>{clearInterval(s),t(new Error("WebSocket reconnect timeout"))}),1e4)}));await e,this.isConnected=!0,console.log("WebSocket reconnected successfully"),await this.fetchConversations(),this.activeConversation&&await this.selectConversation(this.activeConversation)}catch(e){console.error("Failed to reconnect WebSocket:",e)}}),5e3)},async selectConversation(e){this.activeConversation=e;try{const t=this.conversations.find((t=>t.conversation_id===e));if(!t)throw new Error("Conversation not found");this.selectedCourseId=t.course_id;const s=await jt.A.get("/chat/conversation-messages",{params:{conversation_id:e,course_name:t.course_name},headers:{Authorization:this.getCookie("token")}});this.messages=[...s.data.messages],this.rating=s.data.rating||null,this.$nextTick((()=>{this.scrollToBottom()})),await this.markMessagesAsRead()}catch(t){console.error("Failed to fetch conversation messages:",t)}},async markMessagesAsRead(){try{await jt.A.post("/chat/read-conversation",{conversation_id:this.activeConversation},{headers:{Authorization:this.getCookie("token")}}),this.messages.forEach((e=>{0!==e.sender||e.is_read||(e.is_read=!0)}))}catch(e){console.error("Failed to mark messages as read:",e)}},async sendMessage(){if(!this.newMessage.trim())return;const e=this.newMessage;this.newMessage="";try{const t=await jt.A.post("/chat/send-message",{conversation_id:this.activeConversation,content:e},{headers:{Authorization:this.getCookie("token")}});this.messages.push({message_id:t.data.message_id,content:e,sender:1,created_at:(new Date).toISOString(),is_read:!1}),this.$nextTick((()=>{this.scrollToBottom()})),await this.markMessagesAsRead(),await this.fetchConversations()}catch(t){console.error("Failed to send message:",t)}},scrollToBottom(){setTimeout((()=>{const e=this.$refs.messageScrollbar;if(e){const t=e.$el.querySelector(".el-scrollbar__wrap");t&&(t.scrollTop=t.scrollHeight)}}),50)},handleKeyDown(e){e.ctrlKey&&"Enter"===e.key&&this.sendMessage()},getCookie(e){const t=document.cookie.split("; ");for(let s=0;se.conversation_id===t));s?await this.selectConversation(t):console.warn("Conversation not found for ID:",t)}}};const At=(0,m.A)(Dt,[["render",It],["__scopeId","data-v-6c274ce6"]]);var Ft=At;const Nt={class:"about-container"},Ut={class:"about-page"},$t={class:"version-timeline"};function zt(e,t){const s=(0,a.g2)("el-timeline-item"),o=(0,a.g2)("el-timeline");return(0,a.uX)(),(0,a.CE)("div",Nt,[(0,a.Lk)("div",Ut,[t[5]||(t[5]=(0,a.Lk)("div",{class:"project-intro"},[(0,a.Lk)("h2",null,"关于本项目"),(0,a.Lk)("div",{class:"intro-content"},[(0,a.Lk)("p",null,"NEU小站课程评分系统是专门为东北大学学生设计的课程评价平台。本系统采用全匿名方式,学生可以匿名对课程进行评分和发表评论,帮助其他同学更好地了解课程信息。"),(0,a.Lk)("p",null,"系统支持选修课和必修课的评分,包括通识选修、人文选修、专业方向等多个类别。为了保护用户隐私,发表评论时不会显示用户在NEU小站的用户名,每次评论的昵称均由用户自行定义。"),(0,a.Lk)("p",null,"本系统仅对完成NEU小站校园认证的用户开放,确保信息的真实性和可靠性。未来本系统还计划为校内用户开放评分数据下载。")])],-1)),(0,a.Lk)("div",$t,[t[4]||(t[4]=(0,a.Lk)("h2",null,"更新日志",-1)),(0,a.bF)(o,null,{default:(0,a.k6)((()=>[(0,a.bF)(s,{timestamp:"2025年2月",placement:"top"},{default:(0,a.k6)((()=>t[0]||(t[0]=[(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.1.4"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"优化页面样式和用户体验")])],-1),(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.1.3"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"新增AI课程总结功能,接入DeepSeek V3大模型")])],-1)]))),_:1}),(0,a.bF)(s,{timestamp:"2025年1月",placement:"top"},{default:(0,a.k6)((()=>t[1]||(t[1]=[(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.1.2"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"评论区支持删除自己的评论"),(0,a.Lk)("li",null,'优化了"评分由低到高"排序的逻辑,会先展示有评分(评分不为0)的课程'),(0,a.Lk)("li",null,"新增了2024-2025学年春季学期的140门通识选修课")])],-1)]))),_:1}),(0,a.bF)(s,{timestamp:"2024年11月",placement:"top"},{default:(0,a.k6)((()=>t[2]||(t[2]=[(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.1.0"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"新增在线聊天功能"),(0,a.Lk)("li",null,"支持从评论发起聊天")])],-1)]))),_:1}),(0,a.bF)(s,{timestamp:"2024年9月",placement:"top"},{default:(0,a.k6)((()=>t[3]||(t[3]=[(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.0.2"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"新增必修课评分功能"),(0,a.Lk)("li",null,"增加课程类别"),(0,a.Lk)("li",null,"更新用户验证相关接口,增强安全性"),(0,a.Lk)("li",null,"修复部分Bug")])],-1),(0,a.Lk)("div",{class:"version-item"},[(0,a.Lk)("h4",null,"v1.0.0"),(0,a.Lk)("ul",null,[(0,a.Lk)("li",null,"课程评分系统正式上线(测试版)")])],-1)]))),_:1})])),_:1})])])])}const Vt={},Ot=(0,m.A)(Vt,[["render",zt],["__scopeId","data-v-310fde40"]]);var Rt=Ot;const qt=[{path:"/",name:"home",meta:{title:"NEU小站课程评分系统"},component:P},{path:"/courses",name:"course-list",meta:{title:"我的课程 - NEU小站课程评分系统"},component:Pe},{path:"/rating",name:"rating",meta:{title:"选修课列表 - NEU小站课程评分系统"},component:He},{path:"/ratingforcomp",name:"ratingforcomp",meta:{title:"必修课列表 - NEU小站课程评分系统"},component:vt},{path:"/chat",name:"chat",meta:{title:"我的聊天 - NEU小站课程评分系统"},component:Ft},{path:"/about",name:"about",meta:{title:"关于 - NEU小站课程评分系统"},component:Rt}],Bt=(0,f.aE)({history:(0,f.LA)(),routes:qt});Bt.beforeEach(((e,t,s)=>{document.title=e.meta.title||"默认标题",s()}));var Qt=Bt;const Jt=(0,o.Ef)(b);Jt.use(Qt),Jt.use(C.A),Jt.mount("#app"),jt.A.defaults.baseURL="https://coursesystem.xn--xhq44jb2fzpc.com/",Jt.config.globalProperties.$axios=jt.A}},t={};function s(o){var a=t[o];if(void 0!==a)return a.exports;var n=t[o]={exports:{}};return e[o].call(n.exports,n,n.exports,s),n.exports}s.m=e,function(){var e=[];s.O=function(t,o,a,n){if(!o){var i=1/0;for(u=0;u=n)&&Object.keys(s.O).every((function(e){return s.O[e](o[r])}))?o.splice(r--,1):(l=!1,n0&&e[u-1][2]>n;u--)e[u]=e[u-1];e[u]=[o,a,n]}}(),function(){s.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return s.d(t,{a:t}),t}}(),function(){s.d=function(e,t){for(var o in t)s.o(t,o)&&!s.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})}}(),function(){s.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){s.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}}(),function(){var e={524:0};s.O.j=function(t){return 0===e[t]};var t=function(t,o){var a,n,i=o[0],l=o[1],r=o[2],c=0;if(i.some((function(t){return 0!==e[t]}))){for(a in l)s.o(l,a)&&(s.m[a]=l[a]);if(r)var u=r(s)}for(t&&t(o);c
-
-
-
此系统暂不支持手机访问
-
推荐使用电脑访问此系统。
-
使用电脑版样式访问
-
-
-
-
-
+
+
+
-
+
您的访问被拒绝
只有在 NEU小站 完成 校园网或校园邮箱验证 的用户才能访问课程评分系统。
请确保您已完成相关操作,然后重新尝试访问。
@@ -30,7 +21,7 @@
@@ -127,60 +85,76 @@ html, body {
height: 100%;
margin: 0;
padding: 0;
+ background-color: #f5f7fa; /* 浅色背景 */
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
-#app {
+.app-layout {
+ min-height: 100vh;
display: flex;
- height: 100vh;
-}
-
-.sidebar {
- width: 250px;
- background-color: rgb(51,51,51);
- padding: 10px;
- height: 98%;
+ flex-direction: column;
}
.main-content {
- flex-grow: 1;
+ flex: 1;
padding: 20px;
- background-color: white;
- max-width: 98%;
- max-height: 98%;
+ width: 100%;
+ max-width: 1200px;
+ margin: 0 auto;
+ box-sizing: border-box;
}
+/* Forbidden Page Styles */
.forbidden-container {
text-align: center;
- padding: 50px;
+ padding: 50px 20px;
+ display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
+ min-height: 100vh;
}
+.forbidden-title {
+ color: #d9534f;
+ font-size: 2.5rem;
+ margin-bottom: 20px;
+}
+
+.forbidden-text {
+ font-size: 1.25rem;
+ color: #333;
+ margin-bottom: 30px;
+ max-width: 600px;
+}
+
+.forbidden-back-btn {
+ background-color: #5cb85c;
+ color: white;
+ padding: 10px 20px;
+ font-size: 1.1rem;
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+ transition: background-color 0.3s ease;
+}
+
+.forbidden-back-btn:hover {
+ background-color: #4cae4c;
+}
+
+/* Responsive adjustments for main content */
+@media (max-width: 768px) {
+ .main-content {
+ padding: 15px;
+ }
+
.forbidden-title {
- color: #d9534f;
- font-size: 2.5rem;
- margin-bottom: 20px;
+ font-size: 1.8rem;
}
.forbidden-text {
- font-size: 1.25rem;
- color: #333;
- margin-bottom: 30px;
- }
-
- .forbidden-back-btn {
- background-color: #5cb85c;
- color: white;
- padding: 10px 20px;
- font-size: 1.1rem;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- transition: background-color 0.3s ease;
- }
-
- .forbidden-back-btn:hover {
- background-color: #4cae4c;
+ font-size: 1rem;
}
+}
diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue
new file mode 100644
index 0000000..f4c2e40
--- /dev/null
+++ b/src/components/NavBar.vue
@@ -0,0 +1,388 @@
+
+
+
+
+
+
+
课程评分
+
V2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/router/index.js b/src/router/index.js
index aae8ee2..bc6ef75 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -5,6 +5,7 @@ import RatingPage from '../views/RatingPage.vue'
import RatingPageforComp from '../views/RatingPageforComp.vue'
import ChatList from '../views/ChatList.vue'
import AboutPage from '../views/AboutPage.vue'
+import CourseDetail from '../views/CourseDetail.vue'
const routes = [
{
@@ -54,6 +55,14 @@ const routes = [
title: '关于 - NEU小站课程评分系统',
},
component: AboutPage
+ },
+ {
+ path: '/detail/:course_id',
+ name: 'course-detail',
+ meta: {
+ title: '课程详情 - NEU小站课程评分系统',
+ },
+ component: CourseDetail
}
]
diff --git a/src/views/AboutPage.vue b/src/views/AboutPage.vue
index 323ee04..d8b1506 100644
--- a/src/views/AboutPage.vue
+++ b/src/views/AboutPage.vue
@@ -15,6 +15,14 @@
更新日志
+
+
+
v2.0
+
+ 重构响应式UI,优化移动端用户体验。暂时下线聊天功能。
+
+
+
v1.1.4
@@ -169,4 +177,17 @@ h2 {
color: #409EFF;
font-weight: bold;
}
+
+@media (max-width: 768px) {
+ .about-container {
+ height: auto;
+ overflow: visible;
+ padding: 10px;
+ }
+
+ .about-page {
+ overflow-y: visible;
+ height: auto;
+ }
+}
\ No newline at end of file
diff --git a/src/views/ChatList.vue b/src/views/ChatList.vue
index 37bf4e2..69d8169 100644
--- a/src/views/ChatList.vue
+++ b/src/views/ChatList.vue
@@ -1,5 +1,5 @@
-
课程评论
+暂无评论,快来抢沙发吧!
+