




响应式设计的核心理念是"一次开发,处处适配",通过灵活的布局和智能的断点设置,让界面在各种设备上都能完美呈现。




// sw.js - 缓存配置
const CACHE_NAME = 'tongji-orchestra-v5';
const STATIC_CACHE = 'static-cache-v5';
const DYNAMIC_CACHE = 'dynamic-cache-v5';
// 静态资源缓存列表
const urlsToCache = [
'/manifest.json',
'/images/icon-192x192.png',
'/images/icon-512x512.png'
];
// 不缓存大文件和视频
const SKIP_CACHE_PATTERNS = [
/\/uploads\/videos\//,
/\/uploads\/submissions\//,
/files\.666-lufengyuan-nb\.top/, // CDN域名
/\.mp4$/, /\.avi$/
];// config/oss.js - OSS客户端初始化
this.client = new OSS({
region: this.region, // oss-cn-shanghai
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
bucket: this.bucketName, // tongji-orchestra-files
timeout: 60000 // 60秒超时,适合大文件上传
});// config/oss.js - 生成OSS文件路径
generatePath(category, filename) {
const date = new Date();
const year = date.getFullYear();
const month = String(date.getMonth() + 1)
.padStart(2, '0');
return `${category}/${year}/${month}/${filename}`;
// 例如:videos/2025/11/video_1732698765_abc123.mp4
}// config/oss.js - CDN A类型鉴权算法
generateAuthUrl(ossPath, expireTime = 3600) {
const crypto = require('crypto');
const authKey = process.env.CDN_AUTH_KEY;
const timestamp = Math.floor(Date.now() / 1000) + expireTime;
// CDN A类型鉴权算法
const uri = `/${ossPath}`;
const stringToSign = `${uri}-${timestamp}-0-0-${authKey}`;
const md5Hash = crypto.createHash('md5')
.update(stringToSign).digest('hex');
return `https://${this.cdnDomain}${uri}?auth_key=${timestamp}-0-0-${md5Hash}`;
}https://files.666-lufengyuan-nb.top/videos/2025/11/video_123.mp4?auth_key=1732700000-0-0-abc123def456auth_key参数包含三部分信息:过期时间戳、随机数和MD5签名。CDN会验证这些信息,确保请求的合法性。// utils/cdn-preload.js - CDN预热实现
async preloadCache(ossPath, fileType = 'video') {
const preloadUrl = this.generatePreloadAuthUrl(ossPath, 86400); // 24小时有效期// middleware/auth.js - JWT验证中间件
const authenticateToken = async (req, res, next) => {
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ message: '访问令牌缺失' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.userId).select('-password');
if (!user) {
return res.status(401).json({ message: '用户不存在' });
}
if (!user.isActivated) {
return res.status(401).json({ message: '账户未激活' });
}
req.user = user;
next();
} catch (error) {
return res.status(403).json({ message: '无效的访问令牌' });
}
};com.tongji.orchestracom.tongji.orchestra.mail# .github/workflows/android-build.yml
name: Build Android APK
on:
push:
branches: [ main ]
concurrency:
group: android-build-${{ github.ref }}
cancel-in-progress: truemain分支才触发构建jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
- name: Checkout code
uses: actions/checkout@v4- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'- name: Install dependencies
run: npm ci- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'- name: Setup Android SDK
uses: android-actions/setup-android@v3- name: Sync Capacitor
run: npx cap sync android- name: Build Android APK
run: |
cd android
chmod +x ./gradlew
./gradlew assembleStandardDebugchmod +x ./gradlew:给Gradle包装器添加执行权限assembleStandardDebug:构建Standard风味的Debug版本



