diff --git a/.editorconfig b/.editorconfig index 5760be5..e717f5e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,6 +4,7 @@ root = true [*] indent_style = space indent_size = 2 +end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..42295cc --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +TARO_APP_API_BASE_URL= diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9d9ae43 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +* text=auto eol=lf + +# Keep binary assets untouched. +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary diff --git a/.gitignore b/.gitignore index d1df1c0..0f9843e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ npm-debug.log* coverage *.local +.env +.env.* +!.env.example # Editor directories and files .vscode/* diff --git a/README.md b/README.md index 914aca8..b869d17 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ npm run build:weapp ## 🔧 配置说明 ### 环境配置 -- 修改 `src/utils/request.js` 中的 `BASE_URL` 为实际API地址 +- 复制 `.env.example` 为 `.env.local`,并设置 `TARO_APP_API_BASE_URL` - 调整 `src/utils/constants.js` 中的学期配置 ## 贡献指南 diff --git a/config/index.js b/config/index.js index 0cc607c..35c6d8b 100644 --- a/config/index.js +++ b/config/index.js @@ -1,10 +1,42 @@ import { defineConfig } from '@tarojs/cli' +import { existsSync, readFileSync } from 'fs' +import { resolve } from 'path' import { Plugin } from 'vite' import tailwindcss from 'tailwindcss' import { UnifiedViteWeappTailwindcssPlugin as uvtw } from 'weapp-tailwindcss/vite' import devConfig from './dev' import prodConfig from './prod' +const loadLocalEnv = () => { + const envFiles = ['.env.local', '.env'] + + envFiles.forEach((fileName) => { + const filePath = resolve(process.cwd(), fileName) + if (!existsSync(filePath)) return + + readFileSync(filePath, 'utf8') + .split(/\r?\n/) + .forEach((line) => { + const trimmed = line.trim() + if (!trimmed || trimmed.startsWith('#')) return + + const separatorIndex = trimmed.indexOf('=') + if (separatorIndex === -1) return + + const key = trimmed.slice(0, separatorIndex).trim() + const value = trimmed.slice(separatorIndex + 1).trim().replace(/^['"]|['"]$/g, '') + + if (key && process.env[key] === undefined) { + process.env[key] = value + } + }) + }) +} + +loadLocalEnv() + +const API_BASE_URL = process.env.TARO_APP_API_BASE_URL || '' + // https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数 export default defineConfig(async (merge, { command, mode }) => { const baseConfig = { @@ -21,6 +53,7 @@ export default defineConfig(async (merge, { command, mode }) => { outputRoot: 'dist', plugins: [], defineConstants: { + API_BASE_URL: JSON.stringify(API_BASE_URL) }, copy: { patterns: [ diff --git a/src/api/auth.js b/src/api/auth.js index 164d899..ed425f5 100644 --- a/src/api/auth.js +++ b/src/api/auth.js @@ -1,8 +1,44 @@ -import { get, post, put } from '../utils/request' +import { get, post, put, request } from '../utils/request' export const authAPI = { - wechatLogin(code) { - return post('/api/v0/auth/wechat-login', { code }) + wechatLogin(code, options = {}) { + return post('/api/v0/auth/wechat-login', { code }, { + skipAuthRefresh: true, + retryOnAuthFailure: false, + ...options + }) + }, + + refresh(refreshToken, options = {}) { + return post('/api/v0/auth/refresh', { + refresh_token: refreshToken + }, { + skipAuthRefresh: true, + retryOnAuthFailure: false, + ...options + }) + }, + + logout(options = {}) { + return request({ + url: '/api/v0/auth/logout', + method: 'POST', + skipAuthRefresh: true, + retryOnAuthFailure: false, + handleAuthFailure: false, + ...options + }) + }, + + logoutAll(options = {}) { + return request({ + url: '/api/v0/auth/logout-all', + method: 'POST', + skipAuthRefresh: true, + retryOnAuthFailure: false, + handleAuthFailure: false, + ...options + }) } } @@ -13,5 +49,9 @@ export const userAPI = { updateProfile(data) { return put('/api/v0/user/profile', data) + }, + + getLoginDays() { + return get('/api/v0/user/login-days') } } diff --git a/src/api/config.js b/src/api/config.js index 0150b3b..9b826c0 100644 --- a/src/api/config.js +++ b/src/api/config.js @@ -1,24 +1,8 @@ -import { get, post, put, del } from '../utils/request' +import { get } from '../utils/request' export const configAPI = { getConfig(key) { if (!key) return Promise.reject(new Error('Config key is required')) return get(`/api/v0/config/${key}`) }, - - searchConfig(params) { - return get('/api/v0/config/search', params) - }, - - createConfig(data) { - return post('/api/v0/config/', data) - }, - - updateConfig(key, data) { - return put(`/api/v0/config/${key}`, data) - }, - - deleteConfig(key) { - return del(`/api/v0/config/${key}`) - } } diff --git a/src/api/contribution.js b/src/api/contribution.js deleted file mode 100644 index b0739df..0000000 --- a/src/api/contribution.js +++ /dev/null @@ -1,27 +0,0 @@ -import { get, post } from '../utils/request' - -export const contributionAPI = { - createContribution(data) { - return post('/api/v0/contributions', data) - }, - - getContributions(params) { - return get('/api/v0/contributions', params) - }, - - getContributionDetail(id) { - return get(`/api/v0/contributions/${id}`) - }, - - reviewContribution(id, data) { - return post(`/api/v0/contributions/${id}/review`, data) - }, - - getContributionStats() { - return get('/api/v0/contributions/stats') - }, - - getContributionStatsAdmin() { - return get('/api/v0/contributions/stats-admin') - } -} diff --git a/src/api/courseTable.js b/src/api/courseTable.js index 7998d05..50e7b81 100644 --- a/src/api/courseTable.js +++ b/src/api/courseTable.js @@ -1,10 +1,14 @@ -import { get, put, post } from '../utils/request' +import { get, put, del } from '../utils/request' export const courseTableAPI = { getCourseTable(params) { return get('/api/v0/coursetable', params) }, + getBindCount() { + return get('/api/v0/coursetable/bind-count') + }, + searchClass(params) { return get('/api/v0/coursetable/search', params) }, @@ -17,8 +21,8 @@ export const courseTableAPI = { return put('/api/v0/coursetable', data) }, - resetBindCount(userId) { - if (!userId) return Promise.reject(new Error('userId is required')) - return post(`/api/v0/coursetable/reset/${userId}`) + deleteSchedule(semester) { + if (!semester) return Promise.reject(new Error('semester is required')) + return del(`/api/v0/coursetable/schedule?semester=${encodeURIComponent(semester)}`) } } diff --git a/src/api/gpa.js b/src/api/gpa.js new file mode 100644 index 0000000..83f8384 --- /dev/null +++ b/src/api/gpa.js @@ -0,0 +1,19 @@ +import { get, post, del } from '../utils/request' + +export const gpaAPI = { + getBackupList() { + return get('/api/v0/gpa/backup') + }, + + getBackupDetail(id) { + return get(`/api/v0/gpa/backup/${id}`) + }, + + createBackup(data) { + return post('/api/v0/gpa/backup', data) + }, + + deleteBackup(id) { + return del(`/api/v0/gpa/backup/${id}`) + } +} diff --git a/src/api/hero.js b/src/api/hero.js index fdd0ec6..fb4dc6f 100644 --- a/src/api/hero.js +++ b/src/api/hero.js @@ -1,23 +1,7 @@ -import { get, post, put, del } from '../utils/request' +import { get } from '../utils/request' export const heroAPI = { getHeroes() { return get('/api/v0/heroes/') }, - - searchHeroes(params) { - return get('/api/v0/heroes/search', params) - }, - - createHero(data) { - return post('/api/v0/heroes/', data) - }, - - updateHero(id, data) { - return put(`/api/v0/heroes/${id}`, data) - }, - - deleteHero(id) { - return del(`/api/v0/heroes/${id}`) - } } diff --git a/src/api/index.js b/src/api/index.js index 4572a2d..01c028d 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -7,11 +7,12 @@ export { configAPI } from './config' export { ossAPI } from './oss' export { questionsAPI } from './questions' export { notificationAPI } from './notification' -export { contributionAPI } from './contribution' export { materialAPI } from './material' export { systemAPI, statAPI } from './system' export { pointsAPI } from './points' export { dictionaryAPI } from './dictionary' -export { rbacAPI } from './rbac' export { countdownAPI } from './countdown' export { studyTaskAPI } from './studyTask' +export { pomodoroAPI } from './pomodoro' +export { gpaAPI } from './gpa' +export { organizationAPI } from './organization' diff --git a/src/api/material.js b/src/api/material.js index 129838a..e2dd754 100644 --- a/src/api/material.js +++ b/src/api/material.js @@ -29,14 +29,6 @@ export const materialAPI = { return post(`/api/v0/materials/${md5}/download`) }, - deleteMaterial(md5) { - return del(`/api/v0/admin/materials/${md5}`) - }, - - updateMaterialDesc(md5, data) { - return put(`/api/v0/admin/material-desc/${md5}`, data) - }, - getCategories(params) { return get('/api/v0/material-categories', params) } diff --git a/src/api/notification.js b/src/api/notification.js index 0ba6378..b7f8093 100644 --- a/src/api/notification.js +++ b/src/api/notification.js @@ -1,4 +1,4 @@ -import { get, post, put, del } from '../utils/request' +import { get } from '../utils/request' export const notificationAPI = { getNotifications(params) { @@ -9,63 +9,8 @@ export const notificationAPI = { return get(`/api/v0/notifications/${id}`) }, - createNotification(data) { - return post('/api/v0/admin/notifications', data) - }, - - updateNotification(id, data) { - return put(`/api/v0/admin/notifications/${id}`, data) - }, - - publishNotification(id) { - return post(`/api/v0/admin/notifications/${id}/publish`) - }, - - publishAdminNotification(id) { - return post(`/api/v0/admin/notifications/${id}/publish-admin`) - }, - - deleteNotification(id) { - return del(`/api/v0/admin/notifications/${id}`) - }, - - approveNotification(id, data) { - return post(`/api/v0/admin/notifications/${id}/approve`, data) - }, - - getAdminNotifications(params) { - return get('/api/v0/admin/notifications', params) - }, - - getAdminNotificationDetail(id) { - return get(`/api/v0/admin/notifications/${id}`) - }, - getCategories() { return get('/api/v0/categories') }, - createCategory(data) { - return post('/api/v0/admin/categories', data) - }, - - updateCategory(id, data) { - return put(`/api/v0/admin/categories/${id}`, data) - }, - - convertToSchedule(id, data) { - return post(`/api/v0/admin/notifications/${id}/schedule`, data) - }, - - getNotificationStats() { - return get('/api/v0/admin/notifications/stats') - }, - - pinNotification(id) { - return post(`/api/v0/admin/notifications/${id}/pin`) - }, - - unpinNotification(id) { - return post(`/api/v0/admin/notifications/${id}/unpin`) - } } diff --git a/src/api/organization.js b/src/api/organization.js new file mode 100644 index 0000000..84494fc --- /dev/null +++ b/src/api/organization.js @@ -0,0 +1,11 @@ +import { get } from '../utils/request' + +export const organizationAPI = { + getOrganizations(params) { + return get('/api/v0/organizations/', params) + }, + + getOrganizationDetail(id) { + return get(`/api/v0/organizations/${id}`) + }, +} diff --git a/src/api/points.js b/src/api/points.js index 5e81320..505e315 100644 --- a/src/api/points.js +++ b/src/api/points.js @@ -12,8 +12,4 @@ export const pointsAPI = { getStats(params) { return get('/api/v0/points/stats', params) }, - - grantPoints(data) { - return post('/api/v0/points/grant', data) - } } diff --git a/src/api/pomodoro.js b/src/api/pomodoro.js new file mode 100644 index 0000000..6d0a476 --- /dev/null +++ b/src/api/pomodoro.js @@ -0,0 +1,15 @@ +import { get, post } from '../utils/request' + +export const pomodoroAPI = { + increment() { + return post('/api/v0/pomodoro/increment', {}) + }, + + getCount() { + return get('/api/v0/pomodoro/count') + }, + + getRanking() { + return get('/api/v0/pomodoro/ranking') + } +} diff --git a/src/api/rbac.js b/src/api/rbac.js deleted file mode 100644 index a262dd8..0000000 --- a/src/api/rbac.js +++ /dev/null @@ -1,19 +0,0 @@ -import { get, post } from '../utils/request' - -export const rbacAPI = { - getRoles() { - return get('/api/v0/admin/rbac/roles') - }, - - getPermissions() { - return get('/api/v0/admin/rbac/permissions') - }, - - getRolesPermissions() { - return get('/api/v0/admin/rbac/roles/permissions') - }, - - updateUserRoles(userId, data) { - return post(`/api/v0/admin/rbac/users/${userId}/roles`, data) - } -} diff --git a/src/api/review.js b/src/api/review.js index 6b32cc2..eef3064 100644 --- a/src/api/review.js +++ b/src/api/review.js @@ -1,4 +1,4 @@ -import { get, post, del } from '../utils/request' +import { get, post } from '../utils/request' export const reviewAPI = { getTeacherReviews(params) { @@ -12,20 +12,4 @@ export const reviewAPI = { getUserReviews(params) { return get('/api/v0/reviews/user', params) }, - - getAllReviews(params) { - return get('/api/v0/reviews/', params) - }, - - approveReview(id, data) { - return post(`/api/v0/reviews/${id}/approve`, data) - }, - - rejectReview(id, data) { - return post(`/api/v0/reviews/${id}/reject`, data) - }, - - deleteReview(id) { - return del(`/api/v0/reviews/${id}`) - } } diff --git a/src/api/system.js b/src/api/system.js index 77f1cf1..e4b5241 100644 --- a/src/api/system.js +++ b/src/api/system.js @@ -1,21 +1,15 @@ -import Taro from '@tarojs/taro' -import { get } from '../utils/request' +import { get, request } from '../utils/request' export const systemAPI = { healthCheck() { - return new Promise((resolve, reject) => { - Taro.request({ - url: 'https://example.com/health', - method: 'GET', - success: (res) => { - if (res.statusCode >= 200 && res.statusCode < 300) { - resolve(res.data) - } else { - reject(new Error(`Health check failed: HTTP ${res.statusCode}`)) - } - }, - fail: (err) => reject(new Error(err.errMsg || 'Health check failed')) - }) + return request({ + url: '/health', + method: 'GET', + data: {}, + silent: true, + skipAuthRefresh: true, + retryOnAuthFailure: false, + handleAuthFailure: false }) } } diff --git a/src/app.config.js b/src/app.config.js index 8e1e381..98c961a 100644 --- a/src/app.config.js +++ b/src/app.config.js @@ -12,11 +12,6 @@ export default { 'pages/graduation/index', 'pages/map/index', 'pages/teacher-reviews/index', - 'pages/admin/teacher-reviews/index', - 'pages/admin/heroes/index', - 'pages/admin/config/index', - 'pages/admin/rbac/index', - 'pages/admin/points/index', 'pages/terms-of-service/index', 'pages/webview/index', 'pages/hero/index', @@ -26,17 +21,15 @@ export default { 'pages/address/index', 'pages/final-review/index', 'pages/final-review/detail/index', + 'pages/major-transfer/index', + 'pages/competition/index', + 'pages/organization/index', + 'pages/organization/detail/index', + 'pages/qualification/index', + 'pages/exchange/index', // 通知公告相关页面 'pages/notifications/index', 'pages/notifications/detail/index', - 'pages/notifications/create/index', - 'pages/notifications/manage/index', - 'pages/notifications/categories/index', - // 用户投稿相关页面 - 'pages/contributions/create/index', - 'pages/contributions/mine/index', - 'pages/contributions/detail/index', - 'pages/contributions/review/index', // 资料库相关页面 'pages/materials/index', 'pages/materials/detail/index', diff --git a/src/pages/admin/config/index.config.js b/src/pages/admin/config/index.config.js deleted file mode 100644 index 8545c26..0000000 --- a/src/pages/admin/config/index.config.js +++ /dev/null @@ -1,5 +0,0 @@ -export default { - navigationBarTitleText: '配置管理' -} - - diff --git a/src/pages/admin/config/index.vue b/src/pages/admin/config/index.vue deleted file mode 100644 index f1959cc..0000000 --- a/src/pages/admin/config/index.vue +++ /dev/null @@ -1,794 +0,0 @@ -