From 14a0fe8d4f199257fcc5e7d827817de547a05009 Mon Sep 17 00:00:00 2001
From: future <1360317836@qq.com>
Date: Wed, 3 Jun 2026 16:26:44 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=AB=E7=A0=81=E7=AD=BE?=
=?UTF-8?q?=E5=88=B0=E5=8A=9F=E8=83=BD=E5=92=8C=E7=9B=B8=E5=85=B3=E9=85=8D?=
=?UTF-8?q?=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
gym-manage-uniapp/api/index.js | 3 +-
gym-manage-uniapp/api/main.js | 152 +++
.../components/QRCode/StatusCard.vue | 97 ++
.../components/index/QuickEntry.vue | 16 +-
gym-manage-uniapp/manifest.json | 2 +-
gym-manage-uniapp/pages.json | 6 +
gym-manage-uniapp/pages/checkIn/checkIn.vue | 979 ++++++++++++++++++
gym-manage-uniapp/utils/request.js | 215 ++++
gym-manage-uniapp/vite.config.js | 24 +
9 files changed, 1488 insertions(+), 6 deletions(-)
create mode 100644 gym-manage-uniapp/api/main.js
create mode 100644 gym-manage-uniapp/components/QRCode/StatusCard.vue
create mode 100644 gym-manage-uniapp/pages/checkIn/checkIn.vue
create mode 100644 gym-manage-uniapp/utils/request.js
create mode 100644 gym-manage-uniapp/vite.config.js
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 @@
+
+
+
+
+
+
+
+ 生成中...
+
+
+
+
+
+
+
+ 签到成功!
+
+
+
+
+
+
+
+ {{ errorText || '签到失败,请重试' }}
+
+
+
+
+
+
+
\ 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 @@
+
+
+
+
+
+
+
+
+
+
+
+ 尊敬的会员
+
+ 黄金会员
+ 有效期至 2026-12-31
+
+
+
+ 1280
+ 积分
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ QRStatus }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 温馨提示
+
+
+
+ 二维码每5分钟自动刷新,请勿截图使用
+
+
+
+ 签到成功后可进入场馆开始训练
+
+
+
+ 如有问题请联系前台工作人员
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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