Files
wechat-clock-mini/utils/api.js
王宏豪 cd04c1b5ef feat(database): 迁移用户关联字段并优化打卡系统
- 修改数据库配置将MYSQL_DB从mys_info_v3改为mys_info_test
- 新增auth_users表wechat_openid字段并建立唯一索引
- 为plan_checkins表添加计划性能索引(idx_plan_period_student)
- 将checkin_records_old表关联方式从student_id改为user_id
- 将plan_checkins表关联方式从student_id改为user_id并更新附件路径
- 移除routes/auth.py中的uuid导入使用安全token生成函数
- 重构routes/checkin.py打卡逻辑去除course_type字段并优化返回结构
- 添加打卡时间限制验证功能防止过期打卡操作
- 实现小组统计功能支持老师查看各组打卡情况
- 更新主页index.html界面适配新的打卡和计划功能
- 调整计划提交时间规则为周五至周四周期
- 添加月度和年度计划提交状态验证机制
2026-09-10 14:11:58 +08:00

125 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 根据小程序版本自动选择后端地址
function _getBaseUrls() {
let envType = 'release';
try {
const accountInfo = wx.getAccountInfoSync();
envType = accountInfo.miniProgram.envVersion || 'release';
} catch (e) {
// 低版本基础库不支持时默认线上环境
envType = 'release';
}
switch (envType) {
case 'develop':
// 开发版:本地服务
return {
baseUrl: 'https://test.muguaclub.cn/clock',
staticUrl: 'https://test.muguaclub.cn',
h5Url: 'https://test.muguaclub.cn'
};
case 'trial':
// 体验版:测试环境
return {
baseUrl: 'https://test.muguaclub.cn/clock',
staticUrl: 'https://test.muguaclub.cn',
h5Url: 'https://test.muguaclub.cn'
};
case 'release':
default:
// 线上版:正式环境
return {
baseUrl: 'https://m.muguaclub.cn/clock',
staticUrl: 'https://m.muguaclub.cn',
h5Url: 'https://m.muguaclub.cn'
};
}
}
const _urls = _getBaseUrls();
const BASE_URL = _urls.baseUrl;
const STATIC_BASE_URL = _urls.staticUrl;
const H5_BASE_URL = _urls.h5Url;
let redirectingProfile = false;
function goProfile() {
if (redirectingProfile) {
return;
}
const pages = getCurrentPages();
const current = pages.length ? pages[pages.length - 1] : null;
const route = current && current.route;
if (route === 'pages/profile/profile') {
return;
}
redirectingProfile = true;
wx.switchTab({
url: '/pages/profile/profile',
complete() {
setTimeout(() => {
redirectingProfile = false;
}, 1200);
}
});
}
function request(options) {
const { url, method = 'GET', data = {}, auth = true } = options;
const isIdempotent = method === 'GET' || method === 'DELETE';
let retried = false;
return new Promise((resolve, reject) => {
const doRequest = () => {
const header = { 'Content-Type': 'application/json' };
const token = wx.getStorageSync('token');
if (auth && token) {
header['Authorization'] = 'Bearer ' + token;
}
wx.request({
url: BASE_URL + url,
method,
data,
header,
success(res) {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data);
} else if (res.statusCode === 401) {
wx.removeStorageSync('token');
if (auth) {
goProfile();
}
reject(res.data || { error: '未登录' });
} else {
reject(res.data || { error: '请求失败' });
}
},
fail(err) {
// 冷启动时首个请求可能因网络栈未就绪而失败,空闲时对幂等请求自动重试一次
const msg = (err && err.errMsg) || '';
const domainError = /url not in domain list|domain not/i.test(msg);
if (!retried && isIdempotent && !domainError) {
retried = true;
setTimeout(doRequest, 800);
return;
}
reject(err);
}
});
};
doRequest();
});
}
/**
* 把计划附件的相对路径转为完整的静态资源 URL。
* 路径格式:attachments/{user_id}/{plan_type}/{period_key}/{filename}
*/
function planFileUrl(path) {
if (!path) return '';
if (/^https?:\/\//i.test(path)) return path;
const parts = String(path).replace(/^attachments\//, '').split('/');
if (parts.length < 4) return '';
return STATIC_BASE_URL + '/clock/static/plan/' + parts.slice(0, 4).map(encodeURIComponent).join('/');
}
module.exports = { request, planFileUrl, BASE_URL, STATIC_BASE_URL, H5_BASE_URL };