diff --git a/gym-manage-uniapp/api/index.js b/gym-manage-uniapp/api/index.js index f29ddad..2b915c6 100644 --- a/gym-manage-uniapp/api/index.js +++ b/gym-manage-uniapp/api/index.js @@ -1,4 +1,5 @@ -const BASE_URL = 'http://localhost:8080/api' +// const BASE_URL = 'http://localhost:8080/api' +const BASE_URL = '/api' export const request = (options) => { return new Promise((resolve, reject) => { diff --git a/gym-manage-uniapp/api/main.js b/gym-manage-uniapp/api/main.js new file mode 100644 index 0000000..82e695a --- /dev/null +++ b/gym-manage-uniapp/api/main.js @@ -0,0 +1,152 @@ +import { request, setToken, clearToken, clearAllCache, clearCache } from '@/utils/request.js' + +// ========== 登录相关API ========== + +/** + * 微信小程序登录 + * @param {object} data - 登录参数 + * @param {string} data.code - 微信登录code + * @param {string} [data.encryptedData] - 加密数据 + * @param {string} [data.iv] - 加密向量 + * @returns {Promise} 登录结果 + */ +export const login = (data) => { + return request({ + url: '/member/auth/miniapp/login', + method: 'POST', + data: data, + needToken: false // 登录请求不需要token + }).then(res => { + // 登录成功,保存token + if (res.data && res.data.token) { + setToken(res.data.token) + } + return res + }) +} + +/** + * 退出登录 + * @returns {Promise} 退出结果 + */ +export const logout = () => { + return request({ + url: '/member/auth/logout', + method: 'POST' + }).then(res => { + // 退出成功,清除token和缓存 + clearToken() + clearAllCache() + return res + }).catch(err => { + // 即使请求失败,也清除本地token + clearToken() + clearAllCache() + throw err + }) +} + +// ========== 签到相关API ========== + +/** + * 获取签到二维码 + * @param {boolean} [cache=true] - 是否启用缓存 + * @returns {Promise} 二维码数据 + */ +export const getQRCode = (cache = true) => { + return request({ + url: '/checkIn/qrcode', + method: 'GET', + cache: cache, + cacheTime: 5 * 60 * 1000 // 5分钟缓存 + }) +} + +/** + * 扫码签到 + * @param {string} qrContent - 二维码内容 + * @returns {Promise} 签到结果 + */ +export const checkIn = (qrContent) => { + return request({ + url: '/checkIn/scan', + method: 'POST', + data: { qrContent } + }) +} + +// ========== 用户相关API ========== + +/** + * 获取用户信息 + * @param {boolean} [cache=true] - 是否启用缓存 + * @returns {Promise} 用户信息 + */ +export const getUserInfo = (cache = true) => { + return request({ + url: '/member/info', + method: 'GET', + cache: cache, + cacheTime: 30 * 60 * 1000 // 30分钟缓存 + }) +} + +/** + * 更新用户信息 + * @param {object} data - 用户信息 + * @returns {Promise} 更新结果 + */ +export const updateUserInfo = (data) => { + return request({ + url: '/member/info', + method: 'PUT', + data: data + }).then(res => { + // 更新成功,清除用户信息缓存 + const cacheKey = `GET_/member/info_{}` + clearCache(cacheKey) + return res + }) +} + +// ========== 课程相关API ========== + +/** + * 获取推荐课程列表 + * @param {boolean} [cache=true] - 是否启用缓存 + * @returns {Promise} 课程列表 + */ +export const getRecommendCourses = (cache = true) => { + return request({ + url: '/course/recommend', + method: 'GET', + cache: cache, + cacheTime: 10 * 60 * 1000 // 10分钟缓存 + }) +} + +/** + * 获取课程详情 + * @param {number} id - 课程ID + * @param {boolean} [cache=true] - 是否启用缓存 + * @returns {Promise} 课程详情 + */ +export const getCourseDetail = (id, cache = true) => { + return request({ + url: `/course/${id}`, + method: 'GET', + cache: cache, + cacheTime: 15 * 60 * 1000 // 15分钟缓存 + }) +} + +export default { + login, + logout, + getQRCode, + checkIn, + getUserInfo, + updateUserInfo, + getRecommendCourses, + getCourseDetail +} diff --git a/gym-manage-uniapp/components/QRCode/StatusCard.vue b/gym-manage-uniapp/components/QRCode/StatusCard.vue new file mode 100644 index 0000000..3eb316f --- /dev/null +++ b/gym-manage-uniapp/components/QRCode/StatusCard.vue @@ -0,0 +1,97 @@ + + + + + \ No newline at end of file diff --git a/gym-manage-uniapp/components/index/QuickEntry.vue b/gym-manage-uniapp/components/index/QuickEntry.vue index faa9373..dad233c 100644 --- a/gym-manage-uniapp/components/index/QuickEntry.vue +++ b/gym-manage-uniapp/components/index/QuickEntry.vue @@ -6,6 +6,7 @@ v-for="(item, index) in entries" :key="index" class="entry-item" + @tap="QEClick(item.path)" > @@ -21,37 +22,44 @@ diff --git a/gym-manage-uniapp/manifest.json b/gym-manage-uniapp/manifest.json index b801dbc..f6e57db 100644 --- a/gym-manage-uniapp/manifest.json +++ b/gym-manage-uniapp/manifest.json @@ -50,7 +50,7 @@ "quickapp" : {}, /* 小程序特有相关 */ "mp-weixin" : { - "appid" : "wx8278fdbc9f158915", + "appid" : "wx8f0d644d1d8985f6", "setting" : { "urlCheck" : false }, diff --git a/gym-manage-uniapp/pages.json b/gym-manage-uniapp/pages.json index 2f03bac..dacfc0c 100644 --- a/gym-manage-uniapp/pages.json +++ b/gym-manage-uniapp/pages.json @@ -5,6 +5,12 @@ "style": { "navigationBarTitleText": "健身房" } + }, + { + "path": "pages/checkIn/checkIn", + "style": { + "navigationBarTitleText": "会员签到" + } } ], "globalStyle": { diff --git a/gym-manage-uniapp/pages/checkIn/checkIn.vue b/gym-manage-uniapp/pages/checkIn/checkIn.vue new file mode 100644 index 0000000..cf7dc07 --- /dev/null +++ b/gym-manage-uniapp/pages/checkIn/checkIn.vue @@ -0,0 +1,979 @@ + + + + + \ No newline at end of file diff --git a/gym-manage-uniapp/utils/request.js b/gym-manage-uniapp/utils/request.js new file mode 100644 index 0000000..7fed2bf --- /dev/null +++ b/gym-manage-uniapp/utils/request.js @@ -0,0 +1,215 @@ +const BASE_URL = 'http://192.168.43.89:8084/api' + +// 缓存相关常量 +const CACHE_PREFIX = 'API_CACHE_' +const CACHE_EXPIRE_TIME = 5 * 60 * 1000 // 默认缓存时间5分钟 + +/** + * 获取缓存数据 + * @param {string} key - 缓存键名 + * @returns {any} 缓存数据(过期返回null) + */ +export const getCache = (key) => { + try { + const cacheData = uni.getStorageSync(CACHE_PREFIX + key) + if (cacheData && cacheData.expireTime && Date.now() < cacheData.expireTime) { + return cacheData.data + } + // 缓存过期,清除 + uni.removeStorageSync(CACHE_PREFIX + key) + return null + } catch (e) { + console.error('获取缓存失败:', e) + return null + } +} + +/** + * 设置缓存数据 + * @param {string} key - 缓存键名 + * @param {any} data - 要缓存的数据 + * @param {number} expireTime - 过期时间(毫秒),默认5分钟 + */ +export const setCache = (key, data, expireTime = CACHE_EXPIRE_TIME) => { + try { + const cacheData = { + data: data, + expireTime: Date.now() + expireTime + } + uni.setStorageSync(CACHE_PREFIX + key, cacheData) + } catch (e) { + console.error('设置缓存失败:', e) + } +} + +/** + * 清除指定缓存 + * @param {string} key - 缓存键名 + */ +export const clearCache = (key) => { + try { + uni.removeStorageSync(CACHE_PREFIX + key) + } catch (e) { + console.error('清除缓存失败:', e) + } +} + +/** + * 清除所有API缓存 + */ +export const clearAllCache = () => { + try { + const keys = uni.getStorageInfoSync().keys || [] + for (const key of keys) { + if (key.startsWith(CACHE_PREFIX)) { + uni.removeStorageSync(key) + } + } + } catch (e) { + console.error('清除所有缓存失败:', e) + } +} + +/** + * 获取token + * @returns {string|null} token + */ +export const getToken = () => { + try { + return uni.getStorageSync('token') || null + } catch (e) { + console.error('获取token失败:', e) + return null + } +} + +/** + * 设置token + * @param {string} token - token值 + */ +export const setToken = (token) => { + try { + uni.setStorageSync('token', token) + } catch (e) { + console.error('设置token失败:', e) + } +} + +/** + * 清除token + */ +export const clearToken = () => { + try { + uni.removeStorageSync('token') + } catch (e) { + console.error('清除token失败:', e) + } +} + +/** + * 生成请求缓存键名 + * @param {string} url - 请求URL + * @param {object} data - 请求参数 + * @param {string} method - 请求方法 + * @returns {string} 缓存键名 + */ +const generateCacheKey = (url, data, method) => { + const params = JSON.stringify(data || {}) + return `${method}_${url}_${params}` +} + +/** + * 通用请求函数 + * @param {object} options - 请求配置 + * @param {string} options.url - 请求URL + * @param {string} [options.method='GET'] - 请求方法 + * @param {object} [options.data={}] - 请求参数 + * @param {object} [options.header={}] - 请求头 + * @param {boolean} [options.cache=false] - 是否启用缓存 + * @param {number} [options.cacheTime] - 缓存时间(毫秒) + * @param {boolean} [options.needToken=true] - 是否需要token + * @returns {Promise} 请求Promise + */ +export const request = (options) => { + return new Promise((resolve, reject) => { + const { + url, + method = 'GET', + data = {}, + header = {}, + cache = false, + cacheTime, + needToken = true + } = options + + // 生成缓存键名 + const cacheKey = cache ? generateCacheKey(url, data, method) : null + + // 如果启用缓存且存在有效缓存,直接返回缓存数据 + if (cache && cacheKey) { + const cachedData = getCache(cacheKey) + if (cachedData !== null) { + console.log(`[API] 命中缓存: ${url}`) + resolve(cachedData) + return + } + } + + // 构建请求头 + const requestHeader = { + 'Content-Type': 'application/json', + ...header + } + + // 如果需要token,自动添加到请求头 + if (needToken) { + const token = getToken() + if (token) { + requestHeader['Authorization'] = `Bearer ${token}` + } + } + + uni.request({ + url: BASE_URL + url, + method: method, + data: data, + header: requestHeader, + success: (res) => { + if (res.statusCode === 200) { + // 如果启用缓存,保存响应数据 + if (cache && cacheKey && res.data) { + setCache(cacheKey, res.data, cacheTime) + } + resolve(res.data) + } else if (res.statusCode === 401) { + // token过期,清除token并提示重新登录 + clearToken() + uni.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + reject({ code: 401, message: '登录已过期' }) + } else { + reject({ code: res.statusCode, message: res.data?.message || '请求失败' }) + } + }, + fail: (err) => { + console.error(`[API] 请求失败: ${url}`, err) + reject({ code: -1, message: '网络请求失败', error: err }) + } + }) + }) +} + +// 工具函数导出 +export const requestUtils = { + getToken, + setToken, + clearToken, + getCache, + setCache, + clearCache, + clearAllCache +} + +export default request diff --git a/gym-manage-uniapp/vite.config.js b/gym-manage-uniapp/vite.config.js new file mode 100644 index 0000000..e15bb3b --- /dev/null +++ b/gym-manage-uniapp/vite.config.js @@ -0,0 +1,24 @@ +import { defineConfig } from 'vite' +import uni from '@dcloudio/vite-plugin-uni' +import path from 'path' + +// 用来匹配地址,解决跨域问题 +export default defineConfig({ + plugins: [uni()], + resolve: { + alias: { + '@': path.resolve(__dirname, 'src') + }, + }, + server: { + proxy: { + // 匹配所有 /api 开头的请求 + '/api': { + target: 'http://192.168.43.89:8084', // 你的后端SpringBoot地址 + changeOrigin: true, // 开启跨域伪装 + // rewrite: (path) => path.replace(/^\/areyouok/, '') + // 举例:前端请求 /api/login → 代理成 http://localhost:8088/login + } + } + } +}) \ No newline at end of file