diff --git a/gym-manage-uniapp/api/main.js b/gym-manage-uniapp/api/main.js index 0cb7476..916aa2a 100644 --- a/gym-manage-uniapp/api/main.js +++ b/gym-manage-uniapp/api/main.js @@ -1,5 +1,9 @@ import request from "@/utils/request.js" +/** + * 微信小程序登录 + * @param {object} params - 登录参数 { code: string } + */ export function login(params) { return request.post('/member/auth/miniapp/login', params) } @@ -28,23 +32,44 @@ export function oneClickLogin(params) { return request.post('/auth/phone/one-click-login', params) } +/** + * 退出登录 + */ export function logout() { return request.post('/member/auth/logout') } +/** + * 获取签到二维码 + * @param {object} options - 请求选项 { cache: boolean, cacheTime: number } + */ export function getQRCode(options = { cache: true, cacheTime: 5 * 60 * 1000 }) { return request.get('/checkIn/qrcode', {}, options) } +/** + * 扫码签到 + * @param {object} params - { qrcode: string, memberId: number } + */ export function checkIn(params) { return request.post('/checkIn/scan', params) } +/** + * 获取签到记录(分页) + * @param {object} params - { page: number, size: number } + * @param {object} options - 请求选项 + */ export function getCheckInRecords(params = {}, options = {}) { const { page = 0, size = 5 } = params return request.post('/checkIn/page', { page, size }, options) } +/** + * 获取用户未读消息数量 + * @param {number} userId - 用户ID + * @param {object} options - 请求选项 + */ export function getUnreadMessageCount(userId, options = {}) { return request.get(`/messages/user/${userId}/unread`, {}, options) } @@ -109,12 +134,17 @@ export function deleteMessage(id, options = {}) { return request.delete(`/messages/${id}`, {}, options) } +/** + * 获取用户信息(基础信息缓存) + * @param {object} options - 请求选项 { cache: boolean, cacheTime: number } + */ export function getUserInfo(options = { cache: true, cacheTime: 30 * 60 * 1000 }) { return request.get('/member/info', {}, options) } /** * 获取会员详细信息(包含会员卡、积分等) + * @param {object} options - 请求选项 { cache: boolean } */ export function getMemberDetail(options = { cache: false }) { return request.get('/member/info', {}, options) @@ -122,14 +152,17 @@ export function getMemberDetail(options = { cache: false }) { /** * 获取签到统计 - * @param {object} params - 查询参数 - * @param {string} params.startDate - 开始日期(yyyy-MM-dd) - * @param {string} params.endDate - 结束日期(yyyy-MM-dd) + * @param {object} params - 查询参数 { startDate: string, endDate: string } + * @param {object} options - 请求选项 { cache: boolean } */ export function getCheckInStats(params = {}, options = { cache: false }) { return request.get('/checkIn/statistics', params, options) } +/** + * 更新用户信息 + * @param {object} params - 用户信息参数 + */ export function updateUserInfo(params) { return request.put('/member/info', params) } @@ -145,10 +178,156 @@ export function purchaseMemberCard(params) { return request.post('/member-card-records/purchase', params) } +/** + * 获取我的会员卡列表 + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 { cache: boolean } + */ export function getMyMemberCards(memberId, options = { cache: false }) { return request.get(`/member-card-records/my-cards/${memberId}`, {}, options) } +/** + * 获取会员的所有会员卡(支持状态筛选) + * @param {number} memberId - 会员ID + * @param {string} status - 状态筛选:all-全部, active-有效, expired-已失效 + * @param {object} options - 请求选项 + */ +export function getMyMemberCardsWithStatus(memberId, status = 'all', options = { cache: false }) { + return request.get(`/member-card-records/my-cards-with-status/${memberId}`, { status }, options) +} + +/** + * 获取会员的主要有效会员卡(只返回一条) + * 优先返回临期卡,其次返回普通有效卡 + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 { cache: boolean } + */ +export function getPrimaryMemberCard(memberId, options = { cache: false }) { + return request.get(`/member-card-records/primary/${memberId}`, {}, options) +} + +/** + * 获取会员卡交易/流水记录(按会员ID) + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 { cache: boolean } + */ +export function getMemberCardTransactions(memberId, options = { cache: false }) { + return request.get(`/member-card-transactions/member/${memberId}`, {}, options) +} + +/** + * 获取会员卡交易/流水记录(按会员卡记录ID) + * @param {number} recordId - 会员卡记录ID + * @param {object} options - 请求选项 { cache: boolean } + */ +export function getMemberCardTransactionsByRecordId(recordId, options = { cache: false }) { + return request.get(`/member-card-transactions/record/${recordId}`, {}, options) +} + +/** + * 获取当前有效的会员卡列表 + * @param {object} options - 请求选项 { cache: boolean } + */ +export function getActiveMemberCards(options = { cache: false }) { + return request.get('/member-cards/active', {}, options) +} + +/** + * 根据ID获取会员卡详情 + * @param {number} cardId - 会员卡ID + * @param {object} options - 请求选项 { cache: boolean } + */ +export function getMemberCardById(cardId, options = { cache: false }) { + return request.get(`/member-cards/${cardId}`, {}, options) +} + +// ========== 支付密码相关API ========== + +/** + * 检查会员是否已设置支付密码 + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 + */ +export function checkPayPasswordSet(memberId, options = {}) { + return request.get(`/pay-password/check/${memberId}`, {}, options) +} + +/** + * 设置支付密码 + * @param {number} memberId - 会员ID + * @param {string} password - 支付密码 + * @param {object} options - 请求选项 + */ +export function setPayPassword(memberId, password, options = {}) { + return request.post(`/pay-password/set/${memberId}`, { password }, options) +} + +/** + * 验证支付密码 + * @param {number} memberId - 会员ID + * @param {string} password - 支付密码 + * @param {object} options - 请求选项 + */ +export function verifyPayPassword(memberId, password, options = {}) { + return request.post(`/pay-password/verify/${memberId}`, { password }, options) +} + +/** + * 重置支付密码 + * @param {number} memberId - 会员ID + * @param {string} oldPassword - 旧密码 + * @param {string} newPassword - 新密码 + * @param {object} options - 请求选项 + */ +export function resetPayPassword(memberId, oldPassword, newPassword, options = {}) { + return request.post(`/pay-password/reset/${memberId}`, { oldPassword, newPassword }, options) +} + +// ========== 储值卡相关API ========== + +/** + * 获取储值卡信息(包含余额、消费记录等) + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 + */ +export function getStoredCardInfo(memberId, options = {}) { + return request.get(`/stored-card/${memberId}`, {}, options) +} + +/** + * 获取储值卡余额 + * @param {number} memberId - 会员ID + * @param {object} options - 请求选项 + */ +export function getStoredCardBalance(memberId, options = {}) { + return request.get(`/stored-card/${memberId}/balance`, {}, options) +} + +/** + * 储值卡支付(验证密码并扣减余额) + * @param {number} memberId - 会员ID + * @param {string} password - 支付密码 + * @param {number} amount - 支付金额 + * @param {object} options - 请求选项 + */ +export function payWithStoredCard(memberId, password, amount, options = {}) { + return request.post(`/stored-card/pay/${memberId}`, { + password, + amount + }, options) +} + +/** + * 查询储值卡充值记录 + * @param {number} memberId - 会员ID + * @param {number} page - 页码 + * @param {number} size - 每页数量 + */ +export function getStoredCardRechargeRecords(memberId, page = 1, size = 20, options = {}) { + return request.get(`/stored-card/${memberId}/recharges?page=${page}&size=${size}`, {}, options) +} + // ========== 支付相关API ========== /** @@ -175,20 +354,50 @@ export function createPayment(params) { /** * 创建扫码支付订单 - * @param {Object} params - 支付参数 + * @param {object} params - 支付参数 */ export function createQrCodePayment(params) { return request.post('/payment/qrcode/create', params) } /** - * 查询支付状态 + * 查询支付状态(本地数据库) * @param {string} orderId - 订单ID */ export function getPaymentStatus(orderId) { return request.get(`/payment/${orderId}`, {}) } +/** + * 查询汇付官方支付状态 + * @param {string} outOrdId - 商户订单号 + * @param {string} hfSeqId - 汇付全局流水号(可选) + */ +export function queryHuifuTradeByOrderId(outOrdId, hfSeqId = null) { + let url = `/payment/huifu/query?outOrdId=${outOrdId}` + if (hfSeqId) { + url += `&hfSeqId=${hfSeqId}` + } + return request.get(url, {}) +} + +/** + * 查询待支付订单 + * @param {number} memberId - 会员ID + * @param {string} orderType - 订单类型 + */ +export function getPendingOrder(memberId, orderType) { + return request.get(`/payment/pending/${memberId}?orderType=${orderType}`, {}) +} + +/** + * 关闭订单 + * @param {string} orderId - 订单ID + */ +export function closeOrder(orderId) { + return request.post(`/payment/${orderId}/close`, {}) +} + /** * 申请退款 * @param {string} orderId - 订单ID @@ -198,14 +407,30 @@ export function refundPayment(orderId, refundAmt) { return request.post(`/payment/${orderId}/refund`, { refundAmt }) } +// ========== 课程相关API ========== + +/** + * 获取推荐课程列表 + * @param {object} options - 请求选项 { cache: boolean, cacheTime: number } + */ export function getRecommendCourses(options = { cache: true, cacheTime: 10 * 60 * 1000 }) { return request.get('/course/recommend', {}, options) } +/** + * 获取课程详情 + * @param {number} id - 课程ID + * @param {object} options - 请求选项 { cache: boolean, cacheTime: number } + */ export function getCourseDetail(id, options = { cache: true, cacheTime: 15 * 60 * 1000 }) { return request.get(`/course/${id}`, {}, options) } +/** + * 获取团课列表(分页) + * @param {object} params - 查询参数 { page: number, size: number, sort: string, order: string, keyword: string } + * @param {object} options - 请求选项 { cache: boolean, cacheTime: number } + */ export function getGroupCoursePage(params = {}, options = { cache: true, cacheTime: 5 * 60 * 1000 }) { const { page = 0, size = 10, sort = 'id', order = 'asc', keyword } = params return request.post('/groupCourse/page', { page, size, sort, order, keyword }, options) @@ -278,6 +503,12 @@ export default { updateUserInfo, purchaseMemberCard, getMyMemberCards, + getMyMemberCardsWithStatus, + getPrimaryMemberCard, + getStoredCardInfo, + getStoredCardBalance, + payWithStoredCard, + getStoredCardRechargeRecords, createPayment, createQrCodePayment, getPaymentStatus, diff --git a/gym-manage-uniapp/common/constants/routes.js b/gym-manage-uniapp/common/constants/routes.js index bbd1846..003f0be 100644 --- a/gym-manage-uniapp/common/constants/routes.js +++ b/gym-manage-uniapp/common/constants/routes.js @@ -31,7 +31,9 @@ export const PAGE = { REFERRAL: '/pages/memberInfo/referral', MY_COURSES: '/pages/memberInfo/myCourses', CHECK_IN_HISTORY: '/pages/memberInfo/checkInHistory', - PURCHASE_CARD: '/pages/memberInfo/purchaseCard' + PURCHASE_CARD: '/pages/memberInfo/purchaseCard', + SET_PAY_PASSWORD: '/pages/memberInfo/setPayPassword', + RECHARGE_STORED_CARD: '/pages/memberInfo/rechargeStoredCard' } /** 底部 TabBar 页面路径,顺序与 TabBar.vue 一致 */ diff --git a/gym-manage-uniapp/common/hooks/useLoginGuard.js b/gym-manage-uniapp/common/hooks/useLoginGuard.js new file mode 100644 index 0000000..a6e6954 --- /dev/null +++ b/gym-manage-uniapp/common/hooks/useLoginGuard.js @@ -0,0 +1,249 @@ +/** + * 登录拦截Hook + * 用于在需要登录的操作前检查用户登录状态,未登录则弹出登录框 + * + * 使用方式: + * import { useLoginGuard } from '@/common/hooks/useLoginGuard.js' + * + * const { checkLogin, requireLogin } = useLoginGuard() + * + * // 方式1:检查登录状态(返回布尔值) + * if (!checkLogin()) return + * + * // 方式2:需要登录才执行(推荐) + * await requireLogin() + * // 之后的代码只有在登录后才执行 + * + * // 方式3:在点击事件中使用 + * async function handleClick() { + * await requireLogin() + * // 执行需要登录的操作 + * } + */ + +import { getToken } from '@/utils/request.js' +import { loadMemberStore } from '@/common/memberInfo/store.js' + +// 保存当前页面的登录弹窗引用 +let loginModalRef = null + +/** + * 注册登录弹窗组件 + * 在App.vue或页面onMounted中调用 + * @param {Object} modalRef - loginModal组件的ref + */ +export function registerLoginModal(modalRef) { + loginModalRef = modalRef +} + +/** + * 获取当前登录状态 + * @returns {Boolean} + */ +export function isLoggedIn() { + const token = getToken() + const isLoginStorage = uni.getStorageSync('isLogin') + return !!(token || isLoginStorage) +} + +/** + * 获取登录用户信息 + * @returns {Object|null} + */ +export function getLoginUser() { + const store = loadMemberStore() + return store.profile || null +} + +/** + * 使用登录拦截Hook + * @returns {Object} + */ +export function useLoginGuard() { + + /** + * 检查登录状态(同步) + * @returns {Boolean} 是否已登录 + */ + function checkLogin() { + return isLoggedIn() + } + + /** + * 需要登录才继续执行(异步) + * 如果未登录,弹出登录框,等待用户登录或取消 + * @param {Object} options - 配置选项 + * @param {String} options.title - 弹窗标题 + * @param {String} options.subtitle - 弹窗副标题 + * @param {Function} options.onSuccess - 登录成功回调 + * @param {Function} options.onCancel - 取消登录回调 + * @returns {Promise} 是否已登录(用户登录成功返回true,取消返回false) + */ + async function requireLogin(options = {}) { + // 如果已经登录,直接返回true + if (isLoggedIn()) { + return true + } + + // 如果传入了onSuccess回调,先检查 + if (options.onSuccess) { + const store = loadMemberStore() + if (store.profile?.id) { + options.onSuccess(store.profile) + return true + } + } + + // 显示登录弹窗 + return new Promise((resolve) => { + if (!loginModalRef) { + console.warn('[useLoginGuard] 登录弹窗未注册,请先调用 registerLoginModal') + // 尝试跳转到登录页 + uni.navigateTo({ + url: '/pages/memberInfo/login', + fail: () => { + uni.showToast({ + title: '请先登录', + icon: 'none' + }) + } + }) + resolve(false) + return + } + + // 保存resolve函数 + let resolvePromise = resolve + + // 显示登录弹窗 + loginModalRef.show() + + // 监听登录成功 + const loginSuccessHandler = (result) => { + if (options.onSuccess) { + options.onSuccess(result) + } + resolvePromise(true) + } + + // 监听登录失败/取消 + const closeHandler = () => { + if (options.onCancel) { + options.onCancel() + } + resolvePromise(false) + } + + // 注册事件监听 + uni.$once('loginModal:success', loginSuccessHandler) + uni.$once('loginModal:close', closeHandler) + + // 设置超时 + setTimeout(() => { + uni.$off('loginModal:success', loginSuccessHandler) + uni.$off('loginModal:close', closeHandler) + }, 60000) // 60秒超时 + }) + } + + /** + * 安全执行函数(仅登录后执行) + * @param {Function} fn - 要执行的函数 + * @param {Object} options - 配置选项 + * @returns {Promise} 函数返回值或null + */ + async function safeExecute(fn, options = {}) { + const loggedIn = await requireLogin(options) + if (loggedIn && typeof fn === 'function') { + return await fn() + } + return null + } + + /** + * 包装需要登录的API调用 + * @param {Function} apiFn - API函数 + * @param {Array} args - API参数 + * @param {Object} options - 配置选项 + * @returns {Promise} + */ + async function callLoggedInApi(apiFn, args = [], options = {}) { + const loggedIn = await requireLogin(options) + if (loggedIn && typeof apiFn === 'function') { + return await apiFn(...args) + } + throw new Error('用户未登录') + } + + return { + checkLogin, + requireLogin, + safeExecute, + callLoggedInApi, + isLoggedIn, + getLoginUser + } +} + +/** + * 创建登录拦截Mixin(用于选项式API) + * @returns {Object} + */ +export function loginGuardMixin() { + return { + data() { + return { + isLogin: false + } + }, + onLoad() { + this.checkLoginStatus() + }, + onShow() { + this.checkLoginStatus() + }, + methods: { + checkLoginStatus() { + this.isLogin = isLoggedIn() + }, + + async ensureLogin() { + if (!this.isLogin) { + if (!loginModalRef) { + uni.navigateTo({ + url: '/pages/memberInfo/login' + }) + return false + } + loginModalRef.show() + return false + } + return true + } + } + } +} + +/** + * 路由守卫配置 + * 配置需要登录的页面路径 + */ +export const protectedRoutes = [ + '/pages/memberInfo/memberInfo', + '/pages/memberInfo/purchaseCard', + '/pages/memberInfo/memberCard', + '/pages/memberInfo/checkIn', + '/pages/memberInfo/booking', + '/pages/memberInfo/coupons', + '/pages/memberInfo/points', + '/pages/memberInfo/userInfo' +] + +/** + * 检查当前页面是否需要登录 + * @param {String} currentPage - 当前页面路径 + * @returns {Boolean} + */ +export function isProtectedRoute(currentPage) { + return protectedRoutes.some(route => currentPage.includes(route)) +} diff --git a/gym-manage-uniapp/common/memberInfo/index.js b/gym-manage-uniapp/common/memberInfo/index.js index a3700d5..f616a9a 100644 --- a/gym-manage-uniapp/common/memberInfo/index.js +++ b/gym-manage-uniapp/common/memberInfo/index.js @@ -12,7 +12,10 @@ export { cancelOngoingBooking, renewMemberCard, parseLocalDate, - saveUserProfile + saveUserProfile, + getCurrentMemberId, + getLoginMemberInfo, + getToken } from './store.js' export { getLatestBodyTestRecord, diff --git a/gym-manage-uniapp/common/memberInfo/store.js b/gym-manage-uniapp/common/memberInfo/store.js index 68bb547..ec234c8 100644 --- a/gym-manage-uniapp/common/memberInfo/store.js +++ b/gym-manage-uniapp/common/memberInfo/store.js @@ -1,4 +1,3 @@ -import { formatMemberCenterPhone, normalizePhoneForStore } from './format.js' import { getDefaultBodyTestState, mergeBodyTestState, @@ -10,14 +9,36 @@ import { mergeModuleState, finalizeModules } from './moduleStore.js' -import { - getDefaultCourseCatalog, +import { getDefaultCourseCatalog, mergeCourseCatalog, canCancelBooking } from './bookingStore.js' +import { getMemberId as requestGetMemberId } from '@/utils/request.js' const STORAGE_KEY = 'gym_member_info_v1' +/** + * 获取当前登录会员ID + * @deprecated 请使用 @/utils/request.js 中的 getMemberId + */ +export function getCurrentMemberId() { + return requestGetMemberId() +} + +/** + * 获取登录信息 + */ +export function getLoginMemberInfo() { + return uni.getStorageSync('loginMemberInfo') || null +} + +/** + * 获取token + */ +export function getToken() { + return uni.getStorageSync('token') || null +} + export function buildCardTip(remainingDays) { return `距离下次到期还有${remainingDays}天,请及时续费` } @@ -41,12 +62,6 @@ export function syncStats(store) { function finalizeStore(store) { syncStats(store) applyCardInfo(store) - if (store.profile?.avatar) { - store.memberProfile.avatar = store.profile.avatar - } - if (store.profile?.phone) { - store.memberProfile.phone = formatMemberCenterPhone(store.profile.phone) - } const latestBodyTest = getLatestBodyTestRecord(store) if (latestBodyTest) { const previous = store.bodyTest.records[1] @@ -60,11 +75,10 @@ function finalizeStore(store) { function getDefaultStore() { return finalizeStore({ - profile: {}, - memberProfile: {}, stats: {}, cardInfo: {}, card: {}, + cards: [], records: [], ongoingBookings: [], historyBookings: [], @@ -74,7 +88,11 @@ function getDefaultStore() { modules: getDefaultModuleState(), courseCatalog: getDefaultCourseCatalog(), couponPoints: {}, - referral: {} + referral: {}, + storedCard: { + balance: 0, + zeroVerified: false + } }) } @@ -83,11 +101,10 @@ export { getDefaultStore } function mergeDefaults(saved) { const defaults = getDefaultStore() return finalizeStore({ - profile: { ...defaults.profile, ...(saved.profile || {}) }, - memberProfile: { ...defaults.memberProfile, ...(saved.memberProfile || {}) }, stats: { ...defaults.stats, ...(saved.stats || {}) }, cardInfo: { ...defaults.cardInfo, ...(saved.cardInfo || {}) }, card: { ...defaults.card, ...(saved.card || {}) }, + cards: saved.cards?.length ? saved.cards : defaults.cards, records: saved.records?.length ? saved.records : defaults.records, ongoingBookings: saved.ongoingBookings ?? defaults.ongoingBookings, historyBookings: saved.historyBookings ?? defaults.historyBookings, @@ -97,7 +114,8 @@ function mergeDefaults(saved) { modules: mergeModuleState(saved.modules), courseCatalog: mergeCourseCatalog(saved.courseCatalog), couponPoints: { ...defaults.couponPoints, ...(saved.couponPoints || {}) }, - referral: { ...defaults.referral, ...(saved.referral || {}) } + referral: { ...defaults.referral, ...(saved.referral || {}) }, + storedCard: { ...defaults.storedCard, ...(saved.storedCard || {}) } }) } @@ -193,21 +211,33 @@ export function getBookingPreview(store, limit = 2) { return store.ongoingBookings.slice(0, limit).map(toBookingPreviewItem) } +export function getExpiringCards(store, daysThreshold = 30) { + if (!store.cards || store.cards.length === 0) { + return [] + } + return store.cards.filter(card => { + const remainingDays = computeRemainingDays(card.validityEnd || card.expireTime) + return remainingDays > 0 && remainingDays <= daysThreshold + }).sort((a, b) => { + const daysA = computeRemainingDays(a.validityEnd || a.expireTime) + const daysB = computeRemainingDays(b.validityEnd || b.expireTime) + return daysA - daysB + }) +} + export function getCenterPageData(store) { + const expiringCards = getExpiringCards(store, 30) return { - userInfo: { ...store.memberProfile }, stats: { checkInCount: store.stats?.checkInCount ?? 0, trainingHours: store.stats?.trainingHours ?? 0, pointsBalance: store.stats?.pointsBalance ?? 0 }, cardInfo: { ...store.cardInfo }, + expiringCards: expiringCards, bookingPreview: getBookingPreview(store), checkIns: store.checkIns.map((item) => ({ ...item })), - bodyReport: { - ...store.bodyReport, - weight: store.profile.weight || store.bodyReport.weight - }, + bodyReport: { ...store.bodyReport }, couponPoints: { ...store.couponPoints, points: store.stats.pointsBalance @@ -290,16 +320,9 @@ export function renewMemberCard(store, addDays = 90) { } export function saveUserProfile(store, profile) { - const phone = normalizePhoneForStore(profile.phone ?? store.profile.phone) - store.profile = { ...store.profile, ...profile, phone } - store.memberProfile = { - ...store.memberProfile, - name: store.profile.name, - phone: formatMemberCenterPhone(store.profile.phone), - avatar: store.profile.avatar || store.memberProfile.avatar - } - if (store.profile.weight) { - store.bodyReport.weight = store.profile.weight + // 不再保存profile到store,用户信息从loginMemberInfo获取 + if (profile.weight) { + store.bodyReport.weight = profile.weight } finalizeStore(store) saveMemberStore(store) @@ -311,3 +334,17 @@ export function persistMemberStore(store) { saveMemberStore(store) return store } + +export function getStoredCardBalance() { + console.log('[storedCard] 余额不使用缓存,每次从后端读取') + return null +} + +export function saveStoredCardBalance(balance) { + console.log('[storedCard] 余额不使用缓存,跳过保存') + return Number(balance) || 0 +} + +export function clearStoredCardCache() { + console.log('[storedCard] 余额不使用缓存,无需清除') +} diff --git a/gym-manage-uniapp/common/permission.js b/gym-manage-uniapp/common/permission.js new file mode 100644 index 0000000..8381cba --- /dev/null +++ b/gym-manage-uniapp/common/permission.js @@ -0,0 +1,304 @@ +/** + * 路由权限拦截器 + * 自动拦截配置好的路径,未登录时自动弹出登录弹窗 + * + * 使用方式:在 App.vue 中 import 并调用 init() 即可 + * 无需在每个页面单独配置 + */ + +import { getToken } from '@/utils/request.js' + +/** + * 白名单 - 不需要登录即可访问的页面 + */ +const WHITE_LIST = [ + '/pages/index/index', + '/pages/course/course', + '/pages/memberInfo/login', + '/pages/memberInfo/register', + '/pages/memberInfo/forgetPassword', + '/pages/about/about', + '/pages/help/help', + '/pages/notice/notice', + '/pages/product/product', + '/pages/store/store', + '/pages/article/article', + '/pages/search/search' +] + +/** + * 需要登录的页面路径前缀 + * 匹配以下前缀的页面都需要登录 + */ +const LOGIN_REQUIRED_PREFIXES = [ + '/pages/memberInfo/memberCard', + '/pages/memberInfo/purchaseCard', + '/pages/memberInfo/checkIn', + '/pages/memberInfo/booking', + '/pages/memberInfo/coupons', + '/pages/memberInfo/points', + '/pages/memberInfo/userInfo', + '/pages/memberInfo/order', + '/pages/memberInfo/settings', + '/pages/memberInfo/feedback', + '/pages/memberInfo/invite', + '/pages/memberInfo/recharge' +] + +/** + * 需要登录的具体页面路径 + */ +const LOGIN_REQUIRED_PATHS = [ + '/pages/memberInfo/memberInfo' +] + +/** + * 检查当前路径是否需要登录 + * @param {String} url - 页面路径(可能包含query参数) + * @returns {Boolean} + */ +function isNeedLogin(url) { + // 去掉query参数 + const path = url.split('?')[0] + + // 检查白名单 + if (WHITE_LIST.includes(path)) { + return false + } + + // 检查具体路径 + if (LOGIN_REQUIRED_PATHS.includes(path)) { + return true + } + + // 检查路径前缀 + if (LOGIN_REQUIRED_PREFIXES.some(prefix => path.startsWith(prefix))) { + return true + } + + return false +} + +/** + * 检查用户是否已登录 + * @returns {Boolean} + */ +function isLoggedIn() { + const token = getToken() + const isLoginStorage = uni.getStorageSync('isLogin') + return !!(token || isLoginStorage) +} + +/** + * 登录弹窗组件引用(需要在App.vue中注册) + */ +let loginModalRef = null + +/** + * 注册登录弹窗组件 + * @param {Object} modalRef - LoginModal组件的ref + */ +export function registerLoginModal(modalRef) { + loginModalRef = modalRef +} + +/** + * 显示登录弹窗 + */ +function showLoginModal() { + if (loginModalRef) { + loginModalRef.show() + } else { + // 如果没有注册弹窗,跳转到登录页 + uni.navigateTo({ + url: '/pages/memberInfo/login' + }) + } +} + +/** + * 记录用户原本要访问的页面 + * @param {String} url - 页面路径 + */ +function saveRedirectUrl(url) { + uni.setStorageSync('redirectUrl', url) +} + +/** + * 获取用户原本要访问的页面 + * @returns {String|null} + */ +export function getRedirectUrl() { + const url = uni.getStorageSync('redirectUrl') + uni.removeStorageSync('redirectUrl') + return url +} + +/** + * 跳转到用户原本要访问的页面 + */ +export function redirectToSavedUrl() { + const url = getRedirectUrl() + if (url) { + uni.navigateTo({ + url: url, + fail: () => { + uni.switchTab({ + url: '/pages/index/index' + }) + } + }) + } +} + +/** + * 初始化路由拦截器 + */ +export function initPermissionInterceptor() { + console.log('[PermissionInterceptor] 初始化路由拦截器') + + // 拦截 navigateTo + uni.addInterceptor('navigateTo', { + invoke(args) { + const url = args.url + if (isNeedLogin(url) && !isLoggedIn()) { + console.log('[PermissionInterceptor] 拦截 navigateTo:', url) + saveRedirectUrl(url) + showLoginModal() + return false + } + return true + }, + success() { + // 跳转成功 + }, + fail(err) { + console.error('[PermissionInterceptor] navigateTo 失败:', err) + } + }) + + // 拦截 redirectTo + uni.addInterceptor('redirectTo', { + invoke(args) { + const url = args.url + if (isNeedLogin(url) && !isLoggedIn()) { + console.log('[PermissionInterceptor] 拦截 redirectTo:', url) + saveRedirectUrl(url) + showLoginModal() + return false + } + return true + }, + success() {}, + fail(err) { + console.error('[PermissionInterceptor] redirectTo 失败:', err) + } + }) + + // 拦截 reLaunch + uni.addInterceptor('reLaunch', { + invoke(args) { + const url = args.url + if (isNeedLogin(url) && !isLoggedIn()) { + console.log('[PermissionInterceptor] 拦截 reLaunch:', url) + saveRedirectUrl(url) + showLoginModal() + return false + } + return true + }, + success() {}, + fail(err) { + console.error('[PermissionInterceptor] reLaunch 失败:', err) + } + }) + + // 拦截 switchTab + uni.addInterceptor('switchTab', { + invoke(args) { + const url = args.url + if (isNeedLogin(url) && !isLoggedIn()) { + console.log('[PermissionInterceptor] 拦截 switchTab:', url) + saveRedirectUrl(url) + showLoginModal() + return false + } + return true + }, + success() {}, + fail(err) { + console.error('[PermissionInterceptor] switchTab 失败:', err) + } + }) + + // 拦截 navigateBack + uni.addInterceptor('navigateBack', { + invoke() { + return true + }, + success() {}, + fail() {} + }) + + console.log('[PermissionInterceptor] 路由拦截器初始化完成') +} + +/** + * 添加需要登录的页面路径 + * @param {String|Array} paths - 页面路径或路径数组 + */ +export function addLoginRequiredPaths(paths) { + if (Array.isArray(paths)) { + LOGIN_REQUIRED_PATHS.push(...paths) + } else { + LOGIN_REQUIRED_PATHS.push(paths) + } +} + +/** + * 添加需要登录的页面路径前缀 + * @param {String|Array} prefixes - 路径前缀或前缀数组 + */ +export function addLoginRequiredPrefixes(prefixes) { + if (Array.isArray(prefixes)) { + LOGIN_REQUIRED_PREFIXES.push(...prefixes) + } else { + LOGIN_REQUIRED_PREFIXES.push(prefixes) + } +} + +/** + * 添加到白名单 + * @param {String|Array} paths - 页面路径或路径数组 + */ +export function addWhiteList(paths) { + if (Array.isArray(paths)) { + WHITE_LIST.push(...paths) + } else { + WHITE_LIST.push(paths) + } +} + +/** + * 获取当前配置的白名单 + * @returns {Array} + */ +export function getWhiteList() { + return [...WHITE_LIST] +} + +/** + * 获取当前配置的需要登录的路径 + * @returns {Array} + */ +export function getLoginRequiredPaths() { + return [...LOGIN_REQUIRED_PATHS] +} + +/** + * 获取当前配置的需要登录的路径前缀 + * @returns {Array} + */ +export function getLoginRequiredPrefixes() { + return [...LOGIN_REQUIRED_PREFIXES] +} diff --git a/gym-manage-uniapp/common/style/memberInfo/member-info-member-card.css b/gym-manage-uniapp/common/style/memberInfo/member-info-member-card.css index d9a3d97..7374cb6 100644 --- a/gym-manage-uniapp/common/style/memberInfo/member-info-member-card.css +++ b/gym-manage-uniapp/common/style/memberInfo/member-info-member-card.css @@ -360,3 +360,82 @@ flex-grow: 1; flex-basis: 0; } + +.member-card-section__count { + display: flex; + flex-direction: row; + align-items: center; + gap: 4px; + padding: 4px 12px; + border-radius: 12px; + background-color: rgba(255, 255, 255, 0.2); +} + +.member-card-section__count-num { + font-size: var(--font-size-md); + font-family: var(--font-family); + font-weight: 700; + color: var(--text-inverse); +} + +.member-card-section__count-text { + font-size: var(--font-size-xs); + font-family: var(--font-family); + font-weight: 400; + color: rgba(255, 212, 184, 1); +} + +.member-card-preview__tag--expiring { + background-color: #FFE4E4; +} + +.member-card-preview__tag--expiring .member-card-preview__tag-text { + color: #E74C3C; +} + +.member-card-preview__tag--expired { + background-color: rgba(0, 0, 0, 0.2); +} + +.member-card-preview__tag--expired .member-card-preview__tag-text { + color: rgba(255, 255, 255, 0.7); +} + +.member-card-preview__tag--active { + background-color: rgba(255, 255, 255, 0.19); +} + +.member-card-preview__tag--active .member-card-preview__tag-text { + color: var(--text-inverse); +} + +.member-card-preview__days-num--expiring { + color: #FFE4E4; +} + +.member-card-preview__days-num--expired { + color: #FF6B6B; +} + +.member-card-preview__purchase { + flex-shrink: 0; + display: flex; + flex-direction: row; + align-items: center; + padding: 8px 20px; + border-radius: 20px; + background-color: var(--bg-white); +} + +.member-card-preview__purchase-text { + font-size: var(--font-size-base); + font-family: var(--font-family); + font-weight: 600; + color: var(--accent-orange); + width: auto; + height: auto; + position: relative; + flex-shrink: 0; + white-space: nowrap; + flex-grow: 0; +} diff --git a/gym-manage-uniapp/components/TabBar.vue b/gym-manage-uniapp/components/TabBar.vue index f3a8f3c..33933f4 100644 --- a/gym-manage-uniapp/components/TabBar.vue +++ b/gym-manage-uniapp/components/TabBar.vue @@ -61,7 +61,6 @@ const HIDE_TABBAR_PAGES = [ function getActiveIndexFromRoute() { const routePath = getCurrentRoutePath() const index = getTabIndexByRoute(routePath) - console.log('从路由获取索引:', routePath, '->', index) return index >= 0 ? index : 0 } diff --git a/gym-manage-uniapp/components/global/LoginModal.usage.md b/gym-manage-uniapp/components/global/LoginModal.usage.md new file mode 100644 index 0000000..3a45726 --- /dev/null +++ b/gym-manage-uniapp/components/global/LoginModal.usage.md @@ -0,0 +1,233 @@ +/** + * 登录弹窗组件使用示例 + * + * 该组件提供了统一的登录拦截功能,可以在任何页面使用 + */ + +## 方式一:在页面中直接使用LoginModal组件 + +```vue + + + +``` + +## 方式二:使用 useLoginGuard Hook + +```vue + +``` + +## 方式三:在组件中使用登录守卫Mixin + +```vue + +``` + +## 登录弹窗组件Props说明 + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| modelValue | Boolean | false | 控制显示/隐藏 | +| title | String | '登录后享受更多服务' | 弹窗标题 | +| subtitle | String | '登录即表示同意相关协议' | 弹窗副标题 | +| showClose | Boolean | true | 是否显示关闭按钮 | +| modalStyle | String | 'center' | 弹窗样式:'center'居中,'bottom'底部 | +| maskClosable | Boolean | true | 点击遮罩是否关闭 | +| onLoginSuccess | Function | null | 登录成功回调 | +| onLoginError | Function | null | 登录失败回调 | + +## 登录弹窗组件Events + +| 事件名 | 说明 | 回调参数 | +|--------|------|----------| +| update:modelValue | 显示状态变化 | Boolean | +| loginSuccess | 登录成功 | Object: 登录结果 | +| loginError | 登录失败 | Error: 错误对象 | +| close | 弹窗关闭 | - | + +## 登录弹窗组件暴露的方法 + +| 方法名 | 说明 | 参数 | +|--------|------|------| +| show() | 显示弹窗 | - | +| hide() | 隐藏弹窗 | - | +| switchCard(card) | 切换登录方式 | 'phone'一键登录 / 'sms'验证码登录 | + +## 全局登录拦截示例 + +在 `App.vue` 中注册全局登录弹窗: + +```vue + + + +``` + +## API路径配置 + +登录弹窗组件使用的API路径定义在 `@/api/main.js`: + +```javascript +// 一键登录 +export function phoneLogin(data) { + return request.post('/auth/phone/login', data) +} + +// 短信验证码登录 +export function smsLogin(data) { + return request.post('/auth/phone/sms/login', data) +} + +// 发送验证码 +export function sendSmsCode(phone) { + return request.post('/auth/phone/sms/send', { phone }) +} +``` + +如需修改API路径,请编辑 `main.js` 文件中的相应函数。 diff --git a/gym-manage-uniapp/components/global/LoginModal.vue b/gym-manage-uniapp/components/global/LoginModal.vue new file mode 100644 index 0000000..1e20915 --- /dev/null +++ b/gym-manage-uniapp/components/global/LoginModal.vue @@ -0,0 +1,691 @@ + + + + + diff --git a/gym-manage-uniapp/components/global/VerifyCodeInput.vue b/gym-manage-uniapp/components/global/VerifyCodeInput.vue new file mode 100644 index 0000000..211e0ea --- /dev/null +++ b/gym-manage-uniapp/components/global/VerifyCodeInput.vue @@ -0,0 +1,278 @@ + + + + + diff --git a/gym-manage-uniapp/components/memberInfo/MemberInfoMemberCard.vue b/gym-manage-uniapp/components/memberInfo/MemberInfoMemberCard.vue index 8a18cfe..9ad1c04 100644 --- a/gym-manage-uniapp/components/memberInfo/MemberInfoMemberCard.vue +++ b/gym-manage-uniapp/components/memberInfo/MemberInfoMemberCard.vue @@ -1,138 +1,271 @@ diff --git a/gym-manage-uniapp/manifest.json b/gym-manage-uniapp/manifest.json index 82743b3..0114e7c 100644 --- a/gym-manage-uniapp/manifest.json +++ b/gym-manage-uniapp/manifest.json @@ -1,9 +1,9 @@ { "name" : "活氧舱", - "appid" : "__UNI__F058AC0", + "appid" : "__UNI__52E2F0D", "description" : "", - "versionName" : "1.0.0", - "versionCode" : "100", + "versionName" : "1.0.1", + "versionCode" : 101, "transformPx" : false, /* 5+App特有相关 */ "app-plus" : { @@ -17,7 +17,10 @@ "delay" : 0 }, /* 模块配置 */ - "modules" : {}, + "modules" : { + "Barcode" : {}, + "OAuth" : {} + }, /* 应用发布信息 */ "distribute" : { /* android打包配置 */ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/android/ALSDK-PhoneNumberAuthSDK_2.1.9.aar b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/android/ALSDK-PhoneNumberAuthSDK_2.1.9.aar deleted file mode 100644 index 112384c..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/android/ALSDK-PhoneNumberAuthSDK_2.1.9.aar and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@2x.png deleted file mode 100644 index db2ab5b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@3x.png deleted file mode 100644 index 61e1dd6..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_check@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@2x.png deleted file mode 100644 index 96f784b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@3x.png deleted file mode 100644 index d4f2dad..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_close_gray@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@2x.png deleted file mode 100644 index c97068b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@3x.png deleted file mode 100644 index 4ee63e0..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_gray@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@2x.png deleted file mode 100644 index 4faed82..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@3x.png deleted file mode 100644 index e4e17e4..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_nav_back_light@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@2x.png deleted file mode 100644 index e200be8..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@3x.png deleted file mode 100644 index bdc8daa..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.bundle/icon_uncheck@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK deleted file mode 100644 index 4e47ad0..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@2x.png deleted file mode 100644 index db2ab5b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@3x.png deleted file mode 100644 index 61e1dd6..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_check@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@2x.png deleted file mode 100644 index 96f784b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@3x.png deleted file mode 100644 index d4f2dad..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_close_gray@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@2x.png deleted file mode 100644 index c97068b..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@3x.png deleted file mode 100644 index 4ee63e0..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_gray@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@2x.png deleted file mode 100644 index 4faed82..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@3x.png deleted file mode 100644 index e4e17e4..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_nav_back_light@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@2x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@2x.png deleted file mode 100644 index e200be8..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@2x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@3x.png b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@3x.png deleted file mode 100644 index bdc8daa..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/ATAuthSDK.bundle/icon_uncheck@3x.png and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/ATAuthSDK.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/ATAuthSDK.h deleted file mode 100644 index dddf462..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/ATAuthSDK.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// ATAuthSDK.h -// ATAuthSDK -// -// Created by yangli on 2020/11/11. -// Copyright © 2020. All rights reserved. -// - -#import - -//! Project version number for ATAuthSDK. -FOUNDATION_EXPORT double ATAuthSDKVersionNumber; - -//! Project version string for ATAuthSDK. -FOUNDATION_EXPORT const unsigned char ATAuthSDKVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#import "TXCommonHandler.h" -#import "TXCommonUtils.h" -#import "PNSReturnCode.h" -#import "TXCustomModel.h" -#import "PNSReporter.h" -#import "PNSFeatureManager.h" diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSFeatureManager.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSFeatureManager.h deleted file mode 100644 index a10f038..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSFeatureManager.h +++ /dev/null @@ -1,27 +0,0 @@ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface PNSFeatureManager : NSObject - -/// 是否开启供应商级别缓存(默认为私网IP级缓存,开启之后缓存为供应商级别) -@property (class, nonatomic, assign) BOOL enableCacheVendorLevel; - -/// 是否开启运营商类型缓存(默认不开启,开启后会缓存上一次sim卡运营商归属信息) -@property (class, nonatomic, assign) BOOL enableCacheLastVendorInfo; - -/// 是否开启降低网络请求频次模式(默认NO),开启后将跳过配置、埋点等dypns域名访问,不影响登录核心功能 -@property (class, nonatomic, assign) BOOL enableReduceNetworkAccess; - -+ (void)enableCacheVendorLevel:(BOOL)enable; - - -+ (void)enableCacheLastVendorInfo:(BOOL)enable; - - -+ (void)enableReduceNetworkAccess:(BOOL)enable; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReporter.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReporter.h deleted file mode 100644 index 31e4cbc..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReporter.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// PNSReporter.h -// ATAuthSDK -// -// Created by 刘超的MacBook on 2020/5/21. -// Copyright © 2020. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSInteger, PNSLoggerLevel) { - PNSLoggerLevelVerbose = 1, - PNSLoggerLevelDebug, - PNSLoggerLevelInfo, - PNSLoggerLevelWarn, - PNSLoggerLevelError -}; - -@interface PNSReporter : NSObject - -/** - * 控制台日志输出开关,若开启会以PNS_LOGGER为开始标记对日志进行输出,Release模式记得关闭! - * @param enable 开关参数,默认为NO - */ -- (void)setConsolePrintLoggerEnable:(BOOL)enable; - -/** - * 设置埋点上传开关,但不会对通过 setupUploader: 接口实现的自定义上传方法起作用 - * @param enable 开关设置BOOL值,默认为YES - */ -- (void)setUploadEnable:(BOOL)enable DEPRECATED_MSG_ATTRIBUTE("日志不再上传");; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReturnCode.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReturnCode.h deleted file mode 100644 index 0b5ecce..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/PNSReturnCode.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// PNSReturnCode.h -// ATAuthSDK -// -// Created by 刘超的MacBook on 2019/9/4. -// Copyright © 2019. All rights reserved. -// - -#ifndef PNSReturnCode_h -#define PNSReturnCode_h - -#import - -#pragma mark - 该返回码为阿里云号码认证SDK⾃身的返回码,请注意600011及600012错误内均含有运营商返回码,具体错误在碰到之后查阅 https://help.aliyun.com/document_detail/85351.html?spm=a2c4g.11186623.6.561.32a7360cxvWk6H - - -/// 接口成功 -static NSString * const PNSCodeSuccess = @"600000"; -/// 获取运营商配置信息失败 -static NSString * const PNSCodeGetOperatorInfoFailed = @"600004"; -/// 未检测到sim卡 -static NSString * const PNSCodeNoSIMCard = @"600007"; -/// 蜂窝网络未开启或不稳定 -static NSString * const PNSCodeNoCellularNetwork = @"600008"; -/// 无法判运营商 -static NSString * const PNSCodeUnknownOperator = @"600009"; -/// 未知异常 -static NSString * const PNSCodeUnknownError = @"600010"; -/// 获取token失败 -static NSString * const PNSCodeGetTokenFailed = @"600011"; -/// 预取号失败 -static NSString * const PNSCodeGetMaskPhoneFailed = @"600012"; -/// 运营商维护升级,该功能不可用 -static NSString * const PNSCodeInterfaceDemoted = @"600013"; -/// 运营商维护升级,该功能已达最大调用次数 -static NSString * const PNSCodeInterfaceLimited = @"600014"; -/// 接口超时 -static NSString * const PNSCodeInterfaceTimeout = @"600015"; -/// AppID、Appkey解析失败 -static NSString * const PNSCodeDecodeAppInfoFailed = @"600017"; -/// 该号码已被运营商管控,目前只有联通号码有该功能 -static NSString * const PNSCodePhoneBlack = @"600018"; -/// 运营商已切换 -static NSString * const PNSCodeCarrierChanged = @"600021"; -/// 终端环境检测失败(终端不支持认证 / 终端检测参数错误) -static NSString * const PNSCodeEnvCheckFail = @"600025"; - -/*************** 号码认证授权页相关返回码 START ***************/ - -/// 唤起授权页成功 -static NSString * const PNSCodeLoginControllerPresentSuccess = @"600001"; -/// 唤起授权页失败 -static NSString * const PNSCodeLoginControllerPresentFailed = @"600002"; -/// 授权页已加载时不允许调用加速或预取号接口 -static NSString * const PNSCodeCallPreLoginInAuthPage = @"600026"; -/// 点击返回,⽤户取消一键登录 -static NSString * const PNSCodeLoginControllerClickCancel = @"700000"; -/// 点击切换按钮,⽤户取消免密登录 -static NSString * const PNSCodeLoginControllerClickChangeBtn = @"700001"; -/// 点击登录按钮事件 -static NSString * const PNSCodeLoginControllerClickLoginBtn = @"700002"; -/// 点击CheckBox事件 -static NSString * const PNSCodeLoginControllerClickCheckBoxBtn = @"700003"; -/// 点击协议富文本文字 -static NSString * const PNSCodeLoginControllerClickProtocol = @"700004"; -/// 中断页面消失的时候,也就是suspendDisMissVC设置为YES的时候,点击左上角返回按钮时透出的状态码 -static NSString * const PNSCodeLoginControllerSuspendDisMissVC = @"700010"; -/// 授权页已销毁 -static NSString * const PNSCodeLoginControllerDeallocVC = @"700020"; - - -/*************** 号码认证授权页相关返回码 FINISH ***************/ - - -/*************** 二次授权页返回code码 START ***************/ - -/// 点击一键登录拉起授权页二次弹窗 -static NSString * const PNSCodeLoginClickPrivacyAlertView = @"700006"; -/// 隐私协议二次弹窗关闭 -static NSString * const PNSCodeLoginPrivacyAlertViewClose = @"700007"; -/// 隐私协议二次弹窗点击确认并继续 -static NSString * const PNSCodeLoginPrivacyAlertViewClickContinue = @"700008"; -/// 点击隐私协议二次弹窗上的协议富文本文字 -static NSString * const PNSCodeLoginPrivacyAlertViewPrivacyContentClick = @"700009"; - -/*************** 二次授权页返回code码 FINISH ***************/ - -#endif /* PNSReturnCode_h */ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonHandler.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonHandler.h deleted file mode 100644 index a46f533..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonHandler.h +++ /dev/null @@ -1,138 +0,0 @@ -// -// TXCommonHandler.h -// ATAuthSDK -// -// Created by yangli on 15/03/2018. - -#import -#import "TXCustomModel.h" -#import "PNSReporter.h" - - -typedef NS_ENUM(NSInteger, PNSAuthType) { - PNSAuthTypeVerifyToken = 1, //本机号码校验 - PNSAuthTypeLoginToken = 2 //一键登录 -}; - -@interface TXCommonHandler : NSObject - -/** - * 获取该类的单例实例对象 - * @return 单例实例对象 - */ -+ (instancetype _Nonnull )sharedInstance; - -/** - * 获取当前SDK版本号 - * @return 字符串,sdk版本号 - */ -- (NSString *_Nonnull)getVersion; - -/** - * SDK鉴权,app生命周期内调用一次 - * @param info app对应的秘钥 - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, msg:...},其他情况时"resultCode"值请参考PNSReturnCode - * @note 重复调用时以最新info信息为准 - */ -- (void)setAuthSDKInfo:(NSString * _Nonnull)info complete:(void(^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 检查当前环境是否支持一键登录或号码认证,resultDic 返回 PNSCodeSuccess 说明当前环境支持 - * @param authType 服务类型 PNSAuthTypeVerifyToken 本机号码校验流程,PNSAuthTypeLoginToken 一键登录流程 - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, msg:...},其他情况时"resultCode"值请参考PNSReturnCode,只有成功回调才能保障后续接口调用 - */ -- (void)checkEnvAvailableWithAuthType:(PNSAuthType)authType complete:(void (^_Nullable)(NSDictionary * _Nullable resultDic))complete; - -/** - * 加速获取本机号码校验token,防止调用 getVerifyTokenWithTimeout:complete: 获取token时间过长 - * @param timeout 接口超时时间,单位s,默认为3.0s - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, token:..., msg:...},其他情况时"resultCode"值请参考PNSReturnCode - */ -- (void)accelerateVerifyWithTimeout:(NSTimeInterval)timeout complete:(void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 获取本机号码校验Token - * @param timeout 接口超时时间,单位s,默认为3.0s - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, token:..., msg:...},其他情况时"resultCode"值请参考PNSReturnCode - */ -- (void)getVerifyTokenWithTimeout:(NSTimeInterval)timeout complete:(void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 加速一键登录授权页弹起,防止调用 getLoginTokenWithTimeout:controller:model:complete: 等待弹起授权页时间过长 - * @param timeout 接口超时时间,单位s,默认为3.0s - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, msg:...},其他情况时"resultCode"值请参考PNSReturnCode - */ -- (void)accelerateLoginPageWithTimeout:(NSTimeInterval)timeout complete:(void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 获取一键登录Token,调用该接口首先会弹起授权页,点击授权页的登录按钮获取Token - * @warning 注意的是,如果前面没有调用 accelerateLoginPageWithTimeout:complete: 接口,该接口内部会自动先帮我们调用,成功后才会弹起授权页,所以有一个明显的等待过程 - * @param timeout 接口超时时间,单位s,默认为3.0s - * @param controller 唤起自定义授权页的容器,内部会对其进行验证,检查是否符合条件 - * @param model 自定义授权页面选项,可为nil,采用默认的授权页面,具体请参考TXCustomModel.h文件 - * @param complete 结果异步回调到主线程,"resultDic"里面的"resultCode"值请参考PNSReturnCode,如下: - * - * 授权页控件点击事件:700000(点击授权页返回按钮)、700001(点击切换其他登录方式)、 - * 700002(点击登录按钮事件,根据返回字典里面的 "isChecked"字段来区分check box是否被选中,只有被选中的时候内部才会去获取Token)、700003(点击check box事件)、700004(点击协议富文本文字) - 接口回调其他事件:600001(授权页唤起成功)、600002(授权页唤起失败)、600000(成功获取Token)、600011(获取Token失败)、 - * 600015(获取Token超时)、600013(运营商维护升级,该功能不可用)、600014(运营商维护升级,该功能已达最大调用次数)..... - */ -- (void)getLoginTokenWithTimeout:(NSTimeInterval)timeout controller:(UIViewController *_Nonnull)controller model:(TXCustomModel *_Nullable)model complete:(void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 此接口仅用于开发期间用于一键登录页面不同机型尺寸适配调试(可支持模拟器),非正式页面,手机掩码为0,不能正常登录,请开发者注意下 - * @param controller 唤起自定义授权页的容器,内部会对其进行验证,检查是否符合条件 - * @param model 自定义授权页面选项,可为nil,采用默认的授权页面,具体请参考TXCustomModel.h文件 - * @param complete 结果异步回调到主线程,"resultDic"里面的"resultCode"值请参考PNSReturnCode - */ -- (void)debugLoginUIWithController:(UIViewController *_Nonnull)controller model:(TXCustomModel *_Nullable)model complete:(void (^_Nullable)(NSDictionary * _Nonnull resultDic))complete; - -/** - * 授权页弹起后,修改checkbox按钮选中状态,当checkout按钮隐藏时,设置不生效 - */ -- (void)setCheckboxIsChecked:(BOOL)isChecked; - -/** - * 查询授权页checkbox是否勾选,YES:勾选,NO:未勾选 - */ -- (BOOL)queryCheckBoxIsChecked; - -/** - * 授权页协议内容动画执行,注意:必须设置privacyAnimation属性,才会执行动画 - */ -- (void)privacyAnimationStart; - -/** - * 授权页checkbox动画执行,注意:必须设置checkboxAnimation属性,才会执行动画 - */ -- (void)checkboxAnimationStart; - -/** - * 手动隐藏一键登录获取登录Token之后的等待动画,默认为自动隐藏,当设置 TXCustomModel 实例 autoHideLoginLoading = NO 时, 可调用该方法手动隐藏 - */ -- (void)hideLoginLoading; - -/** - * 注销授权页,建议用此方法,对于移动卡授权页的消失会清空一些数据 - * @param flag 是否添加动画 - * @param complete 成功返回 - */ -- (void)cancelLoginVCAnimated:(BOOL)flag complete:(void (^_Nullable)(void))complete; - -/** - * 获取日志埋点相关控制对象 - */ -- (PNSReporter * _Nonnull)getReporter; - -/** - * 关闭二次授权弹窗页 - */ -- (void)closePrivactAlertView; - -/** - * 检查及准备调用环境,resultDic返回PNSCodeSuccess才能调用下面的功能接口 - * @param complete 结果异步回调到主线程,成功时resultDic=@{resultCode:600000, msg:...},其他情况时"resultCode"值请参考PNSReturnCode,只有成功回调才能保障后续接口调用 - */ -- (void)checkEnvAvailableWithComplete:(void (^_Nullable)(NSDictionary * _Nullable resultDic))complete DEPRECATED_MSG_ATTRIBUTE("Please use checkEnvAvailableWithAuthType:complete: instead"); - -@end diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonUtils.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonUtils.h deleted file mode 100644 index a56b6db..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCommonUtils.h +++ /dev/null @@ -1,81 +0,0 @@ -// -// TXCommonUtils.h -// authsdk -// -// Created by yangli on 12/03/2018. - -#import - -@interface TXCommonUtils : NSObject - -/** - 判断当前设备蜂窝数据网络是否开启,即3G/4G - @return 结果 - */ -+ (BOOL)checkDeviceCellularDataEnable; - -/** - 判断当前上网卡运营商是否是中国联通 - @return 结果 - */ -+ (BOOL)isChinaUnicom; - -/** - 判断当前上网卡运营商是否是中国移动 - @return 结果 - */ -+ (BOOL)isChinaMobile; - -/** - 判断当前上网卡运营商是否是中国电信 - @return 结果 - */ -+ (BOOL)isChinaTelecom; - -/** - 获取当前上网卡运营商名称,比如中国移动、中国电信、中国联通 - @return 结果 - */ -+ (NSString *)getCurrentCarrierName; - -/** - 获取当前上网卡网络类型,比如WiFi,4G - @return 结果 - */ -+ (NSString *)getNetworktype; - -/** - 判断当前设备是否有SIM卡 - @return 结果 - */ -+ (BOOL)simSupportedIsOK; - -/** - 判断wwan是否开着(通过p0网卡判断,无wifi或有wifi情况下都能检测到) - @return 结果 - */ -+ (BOOL)isWWANOpen; - -/** - 判断wwan是否开着(仅无wifi情况下) - @return 结果 - */ -+ (BOOL)reachableViaWWAN; - -/** - 获取设备当前网络私网IP地址 - @return 结果 - */ -+ (NSString *)getMobilePrivateIPAddress:(BOOL)preferIPv4; - -/** - 获取当前设备的唯一标识ID - */ -+ (NSString *)getUniqueID; - -/** - 通过颜色设置生成图片,支持弧度设置,比如一键登录按钮背景图片 - */ -+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size isRoundedCorner:(BOOL )isRounded radius:(CGFloat)radius; - -@end diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCustomModel.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCustomModel.h deleted file mode 100644 index fa34651..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Headers/TXCustomModel.h +++ /dev/null @@ -1,453 +0,0 @@ -// -// TXCustomModel.h -// ATAuthSDK -// -// Created by yangli on 2019/4/4. -// Copyright © 2019. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSUInteger, PNSPresentationDirection){ - PNSPresentationDirectionBottom = 0, - PNSPresentationDirectionRight, - PNSPresentationDirectionTop, - PNSPresentationDirectionLeft, -}; - -/** - * 构建控件的frame,view布局时会调用该block得到控件的frame - * @param screenSize 屏幕的size,可以通过该size来判断是横屏还是竖屏 - * @param superViewSize 该控件的super view的size,可以通过该size,辅助该控件重新布局 - * @param frame 控件默认的位置 - * @return 控件新设置的位置 - */ -typedef CGRect(^PNSBuildFrameBlock)(CGSize screenSize, CGSize superViewSize, CGRect frame); - -@interface TXCustomModel : NSObject - -/** - * 说明,可设置的Y轴距离,waring: 以下所有关于Y轴的设置<=0都将不生效,请注意 - * 全屏模式:默认是以375x667pt为基准,其他屏幕尺寸可以根据(ratio = 屏幕高度/667)比率来适配,比如 Y*ratio - */ - -#pragma mark- 全屏、弹窗模式设置 -/** - * 授权页面中,渲染并显示所有控件的view,称content view,不实现该block默认为全屏模式 - * 实现弹窗的方案 x >= 0 || y >= 0 width <= 屏幕宽度 || height <= 屏幕高度 - */ -@property (nonatomic, copy) PNSBuildFrameBlock contentViewFrameBlock; - -#pragma mark- 竖屏、横屏模式设置 -/** 屏幕是否支持旋转方向,默认UIInterfaceOrientationMaskPortrait,注意:在刘海屏,UIInterfaceOrientationMaskPortraitUpsideDown属性慎用! */ -@property (nonatomic, assign) UIInterfaceOrientationMask supportedInterfaceOrientations; - -#pragma mark- 仅弹窗模式属性 -/** 底部蒙层背景颜色,默认黑色 */ -@property (nonatomic, strong) UIColor *alertBlurViewColor; -/** 底部蒙层背景透明度,默认0.5 */ -@property (nonatomic, assign) CGFloat alertBlurViewAlpha; -/** contentView背景颜色,默认白色 */ -@property (nonatomic, strong) UIColor *alertContentViewColor; -/** contentView背景透明度,默认1.0 ,即不透明*/ -@property (nonatomic, assign) CGFloat alertContentViewAlpha; -/** contentView的四个圆角值,顺序为左上,左下,右下,右上,需要填充4个值,不足4个值则无效,如果值<=0则为直角 */ -@property (nonatomic, copy) NSArray *alertCornerRadiusArray; -/** 标题栏背景颜色 */ -@property (nonatomic, strong) UIColor *alertTitleBarColor; -/** 标题栏是否隐藏,默认NO */ -@property (nonatomic, assign) BOOL alertBarIsHidden; -/** 标题栏标题,内容、字体、大小、颜色 */ -@property (nonatomic, copy) NSAttributedString *alertTitle; -/** 标题栏右侧关闭按钮图片设置*/ -@property (nonatomic, strong) UIImage *alertCloseImage; -/** 标题栏右侧关闭按钮是否显示,默认NO*/ -@property (nonatomic, assign) BOOL alertCloseItemIsHidden; - -/** 构建标题栏的frame,view布局或布局发生变化时调用,不实现则按默认处理,实现时仅有height生效 */ -@property (nonatomic, copy) PNSBuildFrameBlock alertTitleBarFrameBlock; -/** 构建标题栏标题的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock alertTitleFrameBlock; -/** 构建标题栏右侧关闭按钮的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock alertCloseItemFrameBlock; - -/** 弹窗位置是否根据键盘弹起关闭动态调整,仅在键盘弹起后遮挡弹窗的情况生效,调整后弹窗将居于键盘上方,默认NO*/ -@property (nonatomic, assign) BOOL alertFrameChangeWithKeyboard; - -#pragma mark- 导航栏(只对全屏模式有效) -/**授权页显示中,导航栏是否隐藏,默认NO*/ -@property (nonatomic, assign) BOOL navIsHidden; -/**授权页push到其他页面后,导航栏是否隐藏,默认NO*/ -@property (nonatomic, assign) BOOL navIsHiddenAfterLoginVCDisappear; -/**是否需要中断返回,如果设置为YES,则点击左上角返回按钮的时候默认页面不消失,同时透出状态码700010,需要自己调用TXCommonHandler cancelLoginVCAnimated方法隐藏页面,默认为NO*/ -@property (nonatomic, assign) BOOL suspendDisMissVC; -/** 导航栏主题色 */ -@property (nonatomic, strong) UIColor *navColor; -/** 导航栏标题,内容、字体、大小、颜色 */ -@property (nonatomic, copy) NSAttributedString *navTitle; -/** 导航栏返回图片 */ -@property (nonatomic, strong) UIImage *navBackImage; -/** 是否隐藏授权页导航栏返回按钮,默认不隐藏 */ -@property (nonatomic, assign) BOOL hideNavBackItem; -/** 导航栏右侧自定义控件,可以在创建该VIEW的时候添加手势操作,或者创建按钮或其他赋值给VIEW */ -@property (nonatomic, strong) UIView *navMoreView; - -/** 构建导航栏返回按钮的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock navBackButtonFrameBlock; -/** 构建导航栏标题的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock navTitleFrameBlock; -/** 构建导航栏右侧more view的frame,view布局或布局发生变化时调用,不实现则按默认处理,边界 CGRectGetMinX(frame) >= (superViewSizeViewSize / 0.3) && CGRectGetWidth(frame) <= (superViewSize.width / 3.0) */ -@property (nonatomic, copy) PNSBuildFrameBlock navMoreViewFrameBlock; - -#pragma mark- 全屏、弹窗模式共同属性 - -#pragma mark- 授权页动画相关 -/** 授权页弹出方向,默认PNSPresentationDirectionBottom,该属性只对自带动画起效,不影响自定义动画 */ -@property (nonatomic, assign) PNSPresentationDirection presentDirection; -/** 授权页显示和消失动画时间,默认为0.25s,<= 0 时关闭动画,该属性只对自带动画起效,不影响自定义动画 **/ -@property (nonatomic, assign) CGFloat animationDuration; - -/** 授权页显示动画(弹窗 & 全屏),不设置或设置为nil默认使用自带动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeForwards 及 delegate) **/ -@property (nonatomic, strong, nullable) CAAnimation *entryAnimation; -/** 授权页消失动画(弹窗 & 全屏),不设置或设置为nil默认使用自带动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeForwards 及 delegate) **/ -@property (nonatomic, strong, nullable) CAAnimation *exitAnimation; - -/** 授权页显示时的背景动画(仅弹窗),不设置或设置为nil默认使用自带动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeForwards 及 delegate) **/ -@property (nonatomic, strong, nullable) CAAnimation *bgEntryAnimation; -/** 授权页消失时的背景动画(仅弹窗),不设置或设置为nil默认使用自带动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeForwards 及 delegate) **/ -@property (nonatomic, strong, nullable) CAAnimation *bgExitAnimation; - -#pragma mark- 状态栏 -/** 状态栏是否隐藏,默认NO */ -@property (nonatomic, assign) BOOL prefersStatusBarHidden; -/** 状态栏主题风格,默认UIStatusBarStyleDefault */ -@property (nonatomic, assign) UIStatusBarStyle preferredStatusBarStyle; - -#pragma mark- 背景 -/** 授权页背景色 */ -@property (nonatomic, strong) UIColor *backgroundColor; -/** 授权页背景图片 */ -@property (nonatomic, strong) UIImage *backgroundImage; -/** 授权页背景图片view的 content mode,默认为 UIViewContentModeScaleAspectFill */ -@property (nonatomic, assign) UIViewContentMode backgroundImageContentMode; -/** 点击授权页背景是否关闭授权页,只有在弹窗模式下生效,默认NO*/ -@property (nonatomic, assign) BOOL tapAuthPageMaskClosePage; - -#pragma mark- logo图片 -/** logo图片设置 */ -@property (nonatomic, strong) UIImage *logoImage; -/** logo是否隐藏,默认NO */ -@property (nonatomic, assign) BOOL logoIsHidden; - -/** 构建logo的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock logoFrameBlock; -/** logo的宽设置 */ -@property (nonatomic, assign) CGFloat logoWidth DEPRECATED_MSG_ATTRIBUTE("Please use logoFrameBlock instead"); -/** logo的高设置 */ -@property (nonatomic, assign) CGFloat logoHeight DEPRECATED_MSG_ATTRIBUTE("Please use logoFrameBlock instead"); -/** logo相对导航栏底部或标题栏底部的Y轴距离 */ -@property (nonatomic, assign) CGFloat logoTopOffetY DEPRECATED_MSG_ATTRIBUTE("Please use logoFrameBlock instead"); - -#pragma mark- slogan -/** slogan文案,内容、字体、大小、颜色 */ -@property (nonatomic, copy) NSAttributedString *sloganText; -/** slogan是否隐藏,默认NO */ -@property (nonatomic, assign) BOOL sloganIsHidden; - -/** 构建slogan的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock sloganFrameBlock; -/** slogan相对导航栏底部或标题栏底部的Y轴距离 */ -@property (nonatomic, assign) CGFloat sloganTopOffetY DEPRECATED_MSG_ATTRIBUTE("Please use sloganFrameBlock instead"); - -#pragma mark- 号码 -/** 号码颜色设置 */ -@property (nonatomic, strong) UIColor *numberColor; -/** 号码字体设置,大小小于16则不生效 */ -@property (nonatomic, strong) UIFont *numberFont; - -/** - * 构建号码的frame,view布局或布局发生变化时调用,只有x、y生效,不实现则按默认处理, - * 注:设置不能超出父视图 content view - */ -@property (nonatomic, copy) PNSBuildFrameBlock numberFrameBlock; -/** - * 号码相对导航栏底部或标题栏底部的Y轴距离,不设置则按默认处理 - * 注:设置超出父视图 content view 时不生效 - */ -@property (nonatomic, assign) CGFloat numberTopOffetY DEPRECATED_MSG_ATTRIBUTE("Please use numberFrameBlock instead"); -/** - * 号码相对屏幕中线的X轴偏移距离,不设置则按默认处理,默认为0水平居中 - * 注:设置不能超出父视图 content view - */ -@property (nonatomic, assign) CGFloat numberOffetX DEPRECATED_MSG_ATTRIBUTE("Please use numberFrameBlock instead"); - -#pragma mark- 登录 -/** 登陆按钮文案,内容、字体、大小、颜色*/ -@property (nonatomic, strong) NSAttributedString *loginBtnText; -/** 登录按钮背景图片组,默认高度50.0pt,@[激活状态的图片,失效状态的图片,高亮状态的图片] */ -@property (nonatomic, strong) NSArray *loginBtnBgImgs; -/** - * 是否显示获取登录Token等待过程的loading组件,默认为YES; - * 设置为NO时,SDK内部不会自动展示loading,适用于完全不需要loading的场景 - */ -@property (nonatomic, assign) BOOL showLoginLoading; -/** - * 是否自动隐藏点击登录按钮之后授权页上转圈的 loading, 默认为YES,在获取登录Token成功后自动隐藏 - * 如果设置为 NO,需要自己手动调用 [[TXCommonHandler sharedInstance] hideLoginLoading] 隐藏 - */ -@property (nonatomic, assign) BOOL autoHideLoginLoading; -/** - * loading组件背景图片,默认为nil不设置; - * 如果设置,显示loading时会在转圈指示器下方显示该背景图 - */ -@property (nonatomic, strong, nullable) UIImage *loadingBackgroundImage; -/** - * 构建登录按钮的frame,view布局或布局发生变化时调用,不实现则按默认处理 - * 注:不能超出父视图 content view,height不能小于20,width不能小于父视图宽度的一半 - */ -@property (nonatomic, copy) PNSBuildFrameBlock loginBtnFrameBlock; -/** - * 登录按钮相对导航栏底部或标题栏底部的Y轴距离,不设置则按默认处理 - * 注:设置超出父视图 content view 时不生效 - */ -@property (nonatomic, assign) CGFloat loginBtnTopOffetY DEPRECATED_MSG_ATTRIBUTE("Please use loginBtnFrameBlock instead"); -/** 登录按钮高度,小于20.0pt不生效,不设置则按默认处理 */ -@property (nonatomic, assign) CGFloat loginBtnHeight DEPRECATED_MSG_ATTRIBUTE("Please use loginBtnFrameBlock instead"); -/** 登录按钮相对content view的左右边距,按钮宽度必须大于等于屏幕的一半,不设置则按默认处理 */ -@property (nonatomic, assign) CGFloat loginBtnLRPadding DEPRECATED_MSG_ATTRIBUTE("Please use loginBtnFrameBlock instead"); - -#pragma mark- 协议 -/** checkBox图片组,[uncheckedImg,checkedImg]*/ -@property (nonatomic, copy) NSArray *checkBoxImages; -/** checkBox图片距离控件边框的填充,默认为 UIEdgeInsetsZero,确保控件大小减去内填充大小为资源图片大小情况下,图片才不会变形 **/ -@property (nonatomic, assign) UIEdgeInsets checkBoxImageEdgeInsets; -/** checkBox是否勾选,默认NO */ -@property (nonatomic, assign) BOOL checkBoxIsChecked; -/** checkBox是否隐藏,默认NO */ -@property (nonatomic, assign) BOOL checkBoxIsHidden; -/** checkBox大小,高宽一样,必须大于0 */ -@property (nonatomic, assign) CGFloat checkBoxWH; -/** checkBox是否和协议内容垂直居中,默认NO,即顶部对齐 */ -@property (nonatomic, assign) BOOL checkBoxVerticalCenter; - -/** 协议1,[协议名称,协议Url],注:三个协议名称不能相同 */ -@property (nonatomic, copy) NSArray *privacyOne; -/** 协议2,[协议名称,协议Url],注:三个协议名称不能相同 */ -@property (nonatomic, copy) NSArray *privacyTwo; -/** 协议3,[协议名称,协议Url],注:三个协议名称不能相同 */ -@property (nonatomic, copy) NSArray *privacyThree; -/** 协议名称之间连接字符串数组,默认 ["和","、","、"] ,即第一个为"和",其他为"、",按顺序读取,为空则取默认 */ -@property (nonatomic, copy) NSArray *privacyConectTexts; -/** 协议内容颜色数组,[非点击文案颜色,点击文案颜色] */ -@property (nonatomic, copy) NSArray *privacyColors; -/** 运营商协议内容颜色 ,优先级最高,如果privacyOperatorColors不设置,则取privacyColors中的点击文案颜色,privacyColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyOperatorColor; -/** 协议1内容颜色,优先级最高,如果privacyOneColors不设置,则取privacyColors中的点击文案颜色,privacyColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyOneColor; -/** 协议2内容颜色,优先级最高,如果privacyTwoColors不设置,则取privacyColors中的点击文案颜色,privacyColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyTwoColor; -/** 协议3内容颜色,优先级最高,如果privacyThreeColors不设置,则取privacyColors中的点击文案颜色,privacyColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyThreeColor; -/** 协议文案支持居中、居左、居右设置,默认居左 */ -@property (nonatomic, assign) NSTextAlignment privacyAlignment; -/** 协议整体文案,前缀部分文案 */ -@property (nonatomic, copy) NSString *privacyPreText; -/** 协议整体文案,后缀部分文案 */ -@property (nonatomic, copy) NSString *privacySufText; -/** 运营商协议名称前缀文案,仅支持 <([《(【『 */ -@property (nonatomic, copy) NSString *privacyOperatorPreText; -/** 运营商协议名称后缀文案,仅支持 >)]》)】』*/ -@property (nonatomic, copy) NSString *privacyOperatorSufText; -/** 运营商协议指定显示顺序,默认0,即第1个协议显示,最大值可为3,即第4个协议显示*/ -@property (nonatomic, assign) NSInteger privacyOperatorIndex; -/** 协议整体文案字体,小于10.0不生效 */ -@property (nonatomic, strong) UIFont *privacyFont; -/** 协议整体文案行间距,默认0 */ -@property (nonatomic, assign) CGFloat privacyLineSpaceDp; -/** 运营商协议文案字体,仅对运营商协议本体文案和前后缀生效,小于10.0不生效 */ -@property (nonatomic, strong) UIFont *privacyOperatorFont; -/** 运营商协议文案下划线,仅对运营商协议本体文案和前后缀生效,YES:展示下划线;NO:不展示下划线,默认不展示 */ -@property (nonatomic, assign) BOOL privacyOperatorUnderline; -/** checkBox是否扩大按钮可交互范围至"协议前缀部分文案(默认:我已阅读并同意)"区域,默认NO */ -@property (nonatomic, assign) BOOL expandAuthPageCheckedScope; - -/** - * 构建协议整体(包括checkBox)的frame,view布局或布局发生变化时调用,不实现则按默认处理 - * 如果设置的width小于checkBox的宽则不生效,最小x、y为0,最大width、height为父试图宽高 - * 最终会根据设置进来的width对协议文本进行自适应,得到的size是协议控件的最终大小 - */ -@property (nonatomic, copy) PNSBuildFrameBlock privacyFrameBlock; -/** - * 未同意协议时点击登录按钮,协议整体文案的动画效果,不设置或设置为nil默认没有动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeRemoved 及 delegate) - */ -@property (nonatomic, strong, nullable) CAAnimation *privacyAnimation; -/** - * 未同意协议时点击登录按钮,checkbox的动画效果,不设置或设置为nil默认没有动画,SDK内部会主动更改动画的一些属性(包括:removedOnCompletion = NO、fillMode = kCAFillModeRemoved 及 delegate) - */ -@property (nonatomic, strong, nullable) CAAnimation *checkboxAnimation; -/** 协议整体相对屏幕底部的Y轴距离,与其他有区别!!不能小于0 */ -@property (nonatomic, assign) CGFloat privacyBottomOffetY DEPRECATED_MSG_ATTRIBUTE("Please use privacyFrameBlock instead"); -/** 协议整体(包括checkBox)相对content view的左右边距,当协议整体宽度小于(content view宽度-2*左右边距)且居中模式,则左右边距设置无效,不能小于0 */ -@property (nonatomic, assign) CGFloat privacyLRPadding DEPRECATED_MSG_ATTRIBUTE("Please use privacyFrameBlock instead"); - -#pragma mark- 切换到其他方式 -/** changeBtn标题,内容、字体、大小、颜色 */ -@property (nonatomic, copy) NSAttributedString *changeBtnTitle; -/** changeBtn是否隐藏,默认NO*/ -@property (nonatomic, assign) BOOL changeBtnIsHidden; - -/** 构建changeBtn的frame,view布局或布局发生变化时调用,不实现则按默认处理 */ -@property (nonatomic, copy) PNSBuildFrameBlock changeBtnFrameBlock; -/** changeBtn相对导航栏底部或标题栏底部的Y轴距离 */ -@property (nonatomic, assign) CGFloat changeBtnTopOffetY DEPRECATED_MSG_ATTRIBUTE("Please use changeBtnFrameBlock instead"); - -#pragma mark- 协议详情页 -/** 协议详情页容器是否自定义,默认NO,若为YES,则根据 PNSCodeLoginControllerClickProtocol 返回码获取协议点击详情信息 */ -@property (nonatomic, assign) BOOL privacyVCIsCustomized; -/** 导航栏背景颜色设置 */ -@property (nonatomic, strong) UIColor *privacyNavColor; -/** 导航栏标题字体、大小 */ -@property (nonatomic, strong) UIFont *privacyNavTitleFont; -/** 导航栏标题颜色 */ -@property (nonatomic, strong) UIColor *privacyNavTitleColor; -/** 导航栏返回图片 */ -@property (nonatomic, strong) UIImage *privacyNavBackImage; - -#pragma mark- 其他自定义控件添加及布局 - -/** - * 自定义控件添加,注意:自定义视图的创建初始化和添加到父视图,都需要在主线程!! - * @param superCustomView 父视图 - */ -@property (nonatomic, copy) void(^customViewBlock)(UIView *superCustomView); - -/** - * 每次授权页布局完成时会调用该block,可以在该block实现里面可设置自定义添加控件的frame - * @param screenSize 屏幕的size - * @param contentViewFrame content view的frame, - * @param navFrame 导航栏的frame,仅全屏时有效 - * @param titleBarFrame 标题栏的frame,仅弹窗时有效 - * @param logoFrame logo图片的frame - * @param sloganFrame slogan的frame - * @param numberFrame 号码栏的frame - * @param loginFrame 登录按钮的frame - * @param changeBtnFrame 切换到其他方式按钮的frame - * @param privacyFrame 协议整体(包括checkBox)的frame - */ -@property (nonatomic, copy) void(^customViewLayoutBlock)(CGSize screenSize, CGRect contentViewFrame, CGRect navFrame, CGRect titleBarFrame, CGRect logoFrame, CGRect sloganFrame, CGRect numberFrame, CGRect loginFrame, CGRect changeBtnFrame, CGRect privacyFrame); - -#pragma mark - 二次隐私协议弹窗设置 -/** 二次隐私协议弹窗是否需要显示, 默认NO */ -@property (nonatomic, assign) BOOL privacyAlertIsNeedShow; -/** 二次隐私协议弹窗点击按钮是否需要执行登陆,默认YES */ -@property (nonatomic, assign) BOOL privacyAlertIsNeedAutoLogin; -/** 二次隐私协议弹窗显示/隐藏动画时长,单位秒,默认0.3s,<=0时使用默认值 */ -@property (nonatomic, assign) CGFloat privacyAlertAnimationDuration; -/** 二次隐私协议弹窗显示自定义动画,默认从下往上位移动画 */ -@property (nonatomic, strong, nullable) CAAnimation *privacyAlertEntryAnimation; -/** 二次隐私协议弹窗隐藏自定义动画,默认从上往下位移动画 */ -@property (nonatomic, strong, nullable) CAAnimation *privacyAlertExitAnimation; -/** 二次隐私协议弹窗的四个圆角值,顺序为左上,左下,右下,右上,需要填充4个值,不足4个值则无效,如果值<=0则为直角 ,默认0*/ -@property (nonatomic, copy) NSArray *privacyAlertCornerRadiusArray; -/** 二次隐私协议弹窗背景颜色,默认为白色 */ -@property (nonatomic, strong) UIColor *privacyAlertBackgroundColor; -/** 二次隐私协议弹窗透明度,默认不透明1.0 ,设置范围0.3~1.0之间 */ -@property (nonatomic, assign) CGFloat privacyAlertAlpha; -/** 二次隐私协议弹窗标题文字内容,默认"请阅读并同意以下条款" */ -@property (nonatomic, copy) NSString *privacyAlertTitleContent; -/** 二次隐私协议弹窗标题文字字体,最小10,默认10 */ -@property (nonatomic, strong) UIFont *privacyAlertTitleFont; -/** 二次隐私协议弹窗标题文字颜色,默认黑色 */ -@property (nonatomic, strong) UIColor *privacyAlertTitleColor; -/** 二次隐私协议弹窗标题背景颜色,默认白色*/ -@property (nonatomic, strong) UIColor *privacyAlertTitleBackgroundColor; -/** 二次隐私协议弹窗标题位置,默认居中*/ -@property (nonatomic, assign) NSTextAlignment privacyAlertTitleAlignment; -/** 二次隐私协议弹窗协议内容文字字体,最小10,默认10 */ -@property (nonatomic, strong) UIFont *privacyAlertContentFont; -/** 二次隐私协议弹窗协议内容行间距,默认0 */ -@property (nonatomic, assign) CGFloat privacyAlertLineSpaceDp; -/** 二次隐私协议弹窗协议内容背景颜色,默认白色 */ -@property (nonatomic, strong) UIColor *privacyAlertContentBackgroundColor; -/** 二次隐私协议弹窗协议内容颜色数组,[非点击文案颜色,点击文案颜色],默认[0x999999,0x1890FF] */ -@property (nonatomic, copy) NSArray *privacyAlertContentColors; -/** 二次隐私协议弹窗运营商协议内容文字字体,仅对运营商协议部分的文本生效,最小10,默认10 */ -@property (nonatomic, strong) UIFont *privacyAlertContentOperatorFont; -/** 二次隐私协议弹窗运营商协议内容文字下划线,仅对运营商协议部分的文本生效,YES:展示下划线,NO:不展示下划线,默认不展示 */ -@property (nonatomic, assign) BOOL privacyAlertContentUnderline; -/** 二次隐私协议弹窗协议运营商协议内容颜色,优先级最高,如果privacyAlertOperatorColors不设置,则取privacyAlertContentColors中的点击文案颜色,privacyAlertContentColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyAlertOperatorColor; -/** 二次隐私协议弹窗协议协议1内容颜色 ,优先级最高,如果privacyAlertOneColors不设置,则取privacyAlertContentColors中的点击文案颜色,privacyAlertContentColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyAlertOneColor; -/** 二次隐私协议弹窗协议协议2内容颜色 ,优先级最高,如果privacyAlertTwoColors不设置,则取privacyAlertContentColors中的点击文案颜色,privacyAlertContentColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyAlertTwoColor; -/** 二次隐私协议弹窗协议协议3内容颜色 ,优先级最高,如果privacyAlertThreeColors不设置,则取privacyAlertContentColors中的点击文案颜色,privacyAlertContentColors不设置,则是默认色*/ -@property (nonatomic, strong) UIColor *privacyAlertThreeColor; -/** 二次隐私协议弹窗协议文案支持居中、居左、居右设置,默认居左 */ -@property (nonatomic, assign) NSTextAlignment privacyAlertContentAlignment; - -/** 二次隐私协议弹窗协议整体文案,前缀部分文案 ,如果不赋值,默认使用privacyPreText*/ -@property (nonatomic, copy) NSString *privacyAlertPreText; -/** 二次隐私协议弹窗协议整体文案,后缀部分文案 如果不赋值,默认使用privacySufText*/ -@property (nonatomic, copy) NSString *privacyAlertSufText; - -/** 二次隐私协议弹窗按钮文字内容 默认“同意”*/ -@property (nonatomic, copy) NSString *privacyAlertBtnContent; -/** 二次隐私协议弹窗登录按钮的圆角值,如果值<=0则为直角 ,默认0*/ -@property (nonatomic, assign) CGFloat privacyAlertBtnCornerRadius; -/** 二次隐私协议弹窗按钮按钮背景图片 ,默认高度50.0pt,@[激活状态的图片,高亮状态的图片] */ -@property (nonatomic, copy) NSArray *privacyAlertBtnBackgroundImages; -/** 二次隐私协议弹窗按钮文字颜色,默认黑色, @[激活状态的颜色,高亮状态的颜色] */ -@property (nonatomic, copy) NSArray *privacyAlertButtonTextColors; -/** 二次隐私协议弹窗按钮文字字体,最小10,默认18*/ -@property (nonatomic, strong) UIFont *privacyAlertButtonFont; -/** 二次隐私协议弹窗关闭按钮是否显示,默认显示 */ -@property (nonatomic, assign) BOOL privacyAlertCloseButtonIsNeedShow; -/** 二次隐私协议弹窗右侧关闭按钮图片设置,默认内置的X图片*/ -@property (nonatomic, strong) UIImage *privacyAlertCloseButtonImage; -/** 二次隐私协议弹窗背景蒙层是否显示 ,默认YES*/ -@property (nonatomic, assign) BOOL privacyAlertMaskIsNeedShow; -/** 二次隐私协议弹窗点击背景蒙层是否关闭弹窗 ,默认YES*/ -@property (nonatomic, assign) BOOL tapPrivacyAlertMaskCloseAlert; -/** 二次隐私协议弹窗蒙版背景颜色,默认黑色 */ -@property (nonatomic, strong) UIColor *privacyAlertMaskColor; -/** 二次隐私协议弹窗蒙版透明度 设置范围0.3~1.0之间 ,默认0.5*/ -@property (nonatomic, assign) CGFloat privacyAlertMaskAlpha; -/** 二次隐私协议弹窗蒙版显示动画,默认渐显动画 */ -@property (nonatomic, strong) CAAnimation *privacyAlertMaskEntryAnimation; -/** 二次隐私协议弹窗蒙版消失动画,默认渐隐动画 */ -@property (nonatomic, strong) CAAnimation *privacyAlertMaskExitAnimation; -/** 二次隐私协议弹窗尺寸设置,不能超出父视图 content view,height不能小于50,width不能小于0,默认屏幕居中,宽为屏幕的宽度减掉80,高为200 */ -@property (nonatomic, copy) PNSBuildFrameBlock privacyAlertFrameBlock; -/** 二次隐私协议弹窗标题尺寸,默认x=0,y=0,width=弹窗宽度,最小宽度为100,height=根据文本计算的高度,最小高度为15,不能超出父视图 */ -@property (nonatomic, copy) PNSBuildFrameBlock privacyAlertTitleFrameBlock; -/** 二次隐私协议弹窗内容尺寸,默认为从标题顶部位置开始,最终会根据设置进来的width对协议文本进行自适应,得到的size是协议控件的最终大小。不能超出父视图 */ -@property (nonatomic, copy) PNSBuildFrameBlock privacyAlertPrivacyContentFrameBlock; -/** 二次隐私协议弹窗确认按钮尺寸,默认为父视图的宽度一半,居中显示。高度默认50, */ -@property (nonatomic, copy) PNSBuildFrameBlock privacyAlertButtonFrameBlock; -/** 二次隐私协议弹窗右侧关闭按钮尺寸,默认宽高44,居弹窗右侧15,居弹窗顶部0*/ -@property (nonatomic, copy) PNSBuildFrameBlock privacyAlertCloseFrameBlock; - -/** - * 二次授权页弹窗自定义控件添加,注意:自定义视图的创建初始化和添加到父视图,都需要在主线程!! - * @param superPrivacyAlertCustomView 父视图 - */ -@property (nonatomic, copy) void(^privacyAlertCustomViewBlock)(UIView *superPrivacyAlertCustomView); - -/** - * 二次授权页弹窗布局完成时会调用该block,可以在该block实现里面可设置自定义添加控件的frame - * @param privacyAlertFrame 二次授权页弹窗frame - * @param privacyAlertTitleFrame 二次授权页弹窗标题frame - * @param privacyAlertPrivacyContentFrame 二次授权页弹窗协议内容frame - * @param privacyAlertButtonFrame 二次授权页弹窗确认按钮frame - * @param privacyAlertCloseFrame 二次授权页弹窗右上角关闭按钮frame - */ -@property (nonatomic, copy) void(^privacyAlertCustomViewLayoutBlock)(CGRect privacyAlertFrame, CGRect privacyAlertTitleFrame, CGRect privacyAlertPrivacyContentFrame, CGRect privacyAlertButtonFrame, CGRect privacyAlertCloseFrame); - -@end - -NS_ASSUME_NONNULL_END - diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Info.plist b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Info.plist deleted file mode 100644 index e8fa85f..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Info.plist and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Modules/module.modulemap b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Modules/module.modulemap deleted file mode 100644 index be47bf2..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/Modules/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module ATAuthSDK { - umbrella header "ATAuthSDK.h" - - export * - module * { export * } -} diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/PrivacyInfo.xcprivacy b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/PrivacyInfo.xcprivacy deleted file mode 100644 index b426e43..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDK.framework/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,42 +0,0 @@ - - - - - NSPrivacyCollectedDataTypes - - - NSPrivacyCollectedDataType - NSPrivacyCollectedDataTypeOtherDataTypes - NSPrivacyCollectedDataTypeLinked - - NSPrivacyCollectedDataTypeTracking - - NSPrivacyCollectedDataTypePurposes - - NSPrivacyCollectedDataTypePurposeAnalytics - - - - NSPrivacyTracking - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - - diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/ATAuthSDKUniPlugin b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/ATAuthSDKUniPlugin deleted file mode 100644 index 1269dda..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/ATAuthSDKUniPlugin and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/Info.plist b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/Info.plist deleted file mode 100644 index e9c4e96..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/ATAuthSDKUniPlugin.framework/Info.plist and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMLogger.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMLogger.h deleted file mode 100644 index 9abd531..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMLogger.h +++ /dev/null @@ -1,48 +0,0 @@ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/// 日志级别 -extern NSString * const ACM_LOGGER_LEVEL_VERBOSE; -extern NSString * const ACM_LOGGER_LEVEL_DEBUG; -extern NSString * const ACM_LOGGER_LEVEL_INFO; -extern NSString * const ACM_LOGGER_LEVEL_WARN; -extern NSString * const ACM_LOGGER_LEVEL_ERROR; -extern NSString * const ACM_LOGGER_LEVEL_REALTIME; - -@interface ACMLogger : NSObject - -- (instancetype)init NS_UNAVAILABLE; - -/// 日志是否入库,默认不入库 -@property (nonatomic, assign) BOOL enterDatabase;; - -/// 日志是否允许上传,默认不上传 -@property (nonatomic, assign) BOOL isAllowUpload; - -/** - * 日志入库 - * @param obj 日志的具体内容 - * @param level 日志等级 - */ -- (BOOL)logger:(id)obj level:(NSString *)level ; - -/** - * 上传日志 - * @param startDate 日志开始时间,如果传nil则查询不加该条件 - * @param endDate 日志结束时间,如果传nil则查询不加该条件 - * @param levels 日志等级数组,里面包含对应的日志等级字符串,如果传nil则查询不加该条件 - */ -- (void)uploadLoggersWithLevels:(NSArray * _Nullable)levels - startDate:(NSDate * _Nullable)startDate - endDate:(NSDate * _Nullable)endDate; - -/** - * 上传失败的日志,一般放在重启应用后 - */ -- (void)uploadFailedRecords; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMManager.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMManager.h deleted file mode 100644 index 9c4858a..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMManager.h +++ /dev/null @@ -1,73 +0,0 @@ - -#import -#import -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface ACMManager : NSObject - -/// 日志操作对象 -@property (nonatomic, strong, readonly) ACMLogger *logger; - -/// 埋点操作对象 -@property (nonatomic, strong, readonly) ACMMonitor *monitor; - -- (instancetype)init NS_UNAVAILABLE; - -/** - * 初始化 - * @param databaseName 数据库名,不指定则默认为 “ACMDatabase” - * @param monitorTableName 埋点表名,必须要指定,用来区分不同产品数据 - * @param loggerTablename 日志表名,必须要指定,用来区分不同产品数据 - * @param limitKeyPrefix 限流信息存储到本地key的前缀,用来区分不同产品的限流缓存 - */ -- (instancetype)initWithDatabaseName:(NSString * _Nullable)databaseName - monitorTableName:(NSString *)monitorTableName - loggerTableName:(NSString *)loggerTablename - limitKeyPrefix:(NSString *)limitKeyPrefix; - -/** - * 初始化 - * @param databaseName 数据库名,不指定则默认为 “ACMDatabase” - * @param monitorTableName 埋点表名,必须要指定,用来区分不同产品数据 - * @param loggerTablename 日志表名,必须要指定,用来区分不同产品数据 - * @param limitKeyPrefix 限流信息存储到本地key的前缀,用来区分不同产品的限流缓存 - * @param uploadCount 每次上传条数 - * @param retryRightNow 上传失败是否立马重试,默认立马重试 - * @param uploadOnce 是否只执行一轮上传,默认NO - */ -- (instancetype)initWithDatabaseName:(NSString * _Nullable)databaseName - monitorTableName:(NSString *)monitorTableName - loggerTableName:(NSString *)loggerTablename - limitKeyPrefix:(NSString *)limitKeyPrefix - uploadCount:(NSInteger)uploadCount - retryRightNow:(BOOL)retryRightNow - uploadOnce:(BOOL)uploadOnce; - -/** - * 获取组件当前版本号 - */ -- (NSString *)getVersion; - -/** - * 设置日志埋点上传代理对象 - * 注:这里是强引用 - * @param uploadDelegate 代理对象,需要实现 ACMProtocol 协议 - */ -- (void)setUploadDelegate:(id _Nullable)uploadDelegate; - -/** - * 更新限流相关 - * @param isLimit 是否限流 - * @param limitTimeHour 限流区间大小 - * @param limitCount 区间内限流次数 - */ -- (void)updateLimitConfig:(BOOL)isLimit - limitTimeHour:(NSInteger)limitTimeHour - limitCount:(NSInteger)limitCount; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMMonitor.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMMonitor.h deleted file mode 100644 index f74e3fe..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMMonitor.h +++ /dev/null @@ -1,55 +0,0 @@ - -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef NS_ENUM(NSInteger, ACM_DELETE_TYPE) { - ACM_DELETE_TYPE_ALL, - ACM_DELETE_TYPE_FAILED, - ACM_DELETE_TYPE_UNUPLOAD -}; - - - -@interface ACMMonitor : NSObject - -- (instancetype)init NS_UNAVAILABLE; - -/// 埋点是否入库,默认入库 -@property (nonatomic, assign) BOOL enterDatabase;; - -/// 埋点是否允许上传,默认上传 -@property (nonatomic, assign) BOOL isAllowUpload; - -/** - * 非实时埋点入库 - * @param obj 埋点具体内容 - */ -- (BOOL)monitor:(id)obj; - -/** - * 实时埋点入库 - * @param obj 埋点的具体内容 - */ -- (BOOL)monitorRealtime:(id)obj; - -/** - * 手动触发埋点上传,只上传未上传过的埋点 - */ -- (void)uploadMonitorByManual; - -/** - * 上传失败的埋点,一般放在重启应用后 - */ -- (void)uploadFailedRecords; - -/** - * 删除埋点 - * @param type 删除类型 - * @param block 结果的异步回调 - */ -- (void)deleteRecordsByType:(ACM_DELETE_TYPE)type block:(void (^)(BOOL))block; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMProtocol.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMProtocol.h deleted file mode 100644 index df94a52..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/ACMProtocol.h +++ /dev/null @@ -1,17 +0,0 @@ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol ACMProtocol - -@required - -/// 埋点抛出,可在抛出里面进行上传 -- (BOOL)uploadMonitors:(NSArray *)monitors; -/// 日志抛出,可在抛出里面进行上传 -- (BOOL)uploadLoggers:(NSArray *)loggers; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/YTXMonitor.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/YTXMonitor.h deleted file mode 100644 index 393206d..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Headers/YTXMonitor.h +++ /dev/null @@ -1,4 +0,0 @@ - -#import -#import - diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Info.plist b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Info.plist deleted file mode 100644 index 4b6fa3c..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Info.plist and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Modules/module.modulemap b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Modules/module.modulemap deleted file mode 100644 index 739e9b1..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/Modules/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module YTXMonitor { - umbrella header "YTXMonitor.h" - export * - - module * { export * } -} diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/PrivacyInfo.xcprivacy b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/PrivacyInfo.xcprivacy deleted file mode 100644 index 433213e..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,34 +0,0 @@ - - - - - NSPrivacyCollectedDataTypes - - - NSPrivacyCollectedDataType - NSPrivacyCollectedDataTypeOtherDataTypes - NSPrivacyCollectedDataTypeLinked - - NSPrivacyCollectedDataTypeTracking - - NSPrivacyCollectedDataTypePurposes - - NSPrivacyCollectedDataTypePurposeAnalytics - - - - NSPrivacyTracking - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - - diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/YTXMonitor b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/YTXMonitor deleted file mode 100644 index a1519d8..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXMonitor.framework/YTXMonitor and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXNetUtils.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXNetUtils.h deleted file mode 100644 index 54e4c9d..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXNetUtils.h +++ /dev/null @@ -1,100 +0,0 @@ -// -// YTXNetUtils.h -// YTXOperators -// -// Created by yangli on 2020/11/9. -// Copyright © 2020 com.alicom. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface YTXNetUtils : NSObject - -/** - 判断当前设备蜂窝数据网络是否开启,即3G/4G - @return 结果 - */ -- (BOOL)checkDeviceCellularDataEnable; - -/** -判断当前上网卡运营商是否是中国联通 -@return 结果 -*/ -- (BOOL)isChinaUnicom; - -/** -判断当前上网卡运营商是否是中国移动 -@return 结果 -*/ -- (BOOL)isChinaMobile; - -/** -判断当前上网卡运营商是否是中国电信 -@return 结果 -*/ -- (BOOL)isChinaTelecom; - -/** -获取当前上网卡运营商名称,比如中国移动、中国电信、中国联通 -@return 结果 -*/ -- (NSString *)getCurrentCarrierName; - -/** -获取当前上网卡运营商编码,比如46000、46001、46003 -@return 结果 -*/ -- (NSString *)getCurrentCarrierCode API_DEPRECATED("废弃,完成不可用,返回空字符串", ios(4.0, 16.0)); - -/** -获取当前上网卡网络类型,比如WiFi,4G -@return 结果 -*/ -- (NSString *)getNetworktype; - -/** -判断当前设备是否有SIM卡 -@return 结果 -*/ -- (BOOL)simSupportedIsOK; - -/** - 判断wwan是否开着(通过p0网卡判断,无wifi或有wifi情况下都能检测到) - @return 结果 - */ -- (BOOL)isWWANOpen; - -/** - 判断WiFi是否开着 - @return 结果 - */ -- (BOOL)isWiFiOpen; - -/** - 判断wwan是否开着(仅无wifi情况下) - @return 结果 - */ -- (BOOL)reachableViaWWAN; - -/** - 获取设备当前网络私网IP地址 - @return 结果 - */ -- (NSString *)getMobilePrivateIPAddress:(BOOL)preferIPv4; - -/** -获取双卡设备下,非上网卡信息 - @return 结果 -*/ -- (NSString *)getOptionalCarrierInfo API_DEPRECATED("废弃,完成不可用,返回空字符串", ios(4.0, 16.0));; - -/** - 获取当前蜂网络Ip地址 - */ -- (NSString *)getCellularIp; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXOperators.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXOperators.h deleted file mode 100644 index 337b073..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXOperators.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// YTXOperators.h -// YTXOperators -// -// Created by yangli on 2020/11/9. -// Copyright © 2020 com.alicom. All rights reserved. -// - -#import - -//! Project version number for YTXOperators. -FOUNDATION_EXPORT double YTXOperatorsVersionNumber; - -//! Project version string for YTXOperators. -FOUNDATION_EXPORT const unsigned char YTXOperatorsVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#import -#import diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXVendorService.h b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXVendorService.h deleted file mode 100644 index d64852f..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Headers/YTXVendorService.h +++ /dev/null @@ -1,85 +0,0 @@ -// -// YTXVendorService.h -// ATAuthSDK -// -// Created by 刘超的MacBook on 2020/1/15. -// Copyright © 2020. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface YTXRequest : NSObject -/// 接口调用超时时间,注:目前内部限制最小超时时间为5s,小于5s则按5s设置 -@property (nonatomic, assign) NSTimeInterval timeout; -/// 是否是蜂窝网络 -@property (nonatomic, assign) BOOL isReachableViaWWAN; -@end - -@interface YTXVendorConfig : NSObject -/// 当前供应商标识:中移互联(cm_zyhl),联通小沃(cu_xw),联通在线(cu_zx),电信世纪龙(ct_sjl) -@property (nonatomic, copy) NSString *vendorKey; -/// 供应商二级标识 -@property (nonatomic, copy) NSString *vendorSubKey; -/// 供应商 access id -@property (nonatomic, copy) NSString *vendorAccessId; -/// 供应商 access secret -@property (nonatomic, copy) NSString *vendorAccessSecret; -@end - -@interface YTXVendorService : NSObject - -/** -* 获取SDK版本号 -*/ -+ (NSString *)getVersion; - -/** -* 获取供应商SDK版本号 -*/ -+ (NSDictionary *)getVendorsVersion; - -/** - * 初始化或更新各个供应商的接口调用对象,根据各个供应商的配置信息 - * @param vendorConfigs 各个供应商配置信息 - */ -- (void)updateVendorHandlers:(NSArray *)vendorConfigs; - -/** - * 获取本机号码校验Token - * @param request 请求参数结构体 - * @param vendorConfig 当前供应商配置信息 - * @param complete 结果回调 - */ -- (void)getVerifyTokenWithRequest:(YTXRequest *)request - vendorConfig:(YTXVendorConfig *)vendorConfig - complete:(void(^)(NSDictionary *response))complete; - -/** - * 获取手机掩码 - * @param request 请求参数结构体 - * @param vendorConfig 当前供应商配置信息 - * @param complete 结果回调 - */ -- (void)getMaskNumberWithRequest:(YTXRequest *)request - vendorConfig:(YTXVendorConfig *)vendorConfig - complete:(void(^)(NSDictionary *response))complete; - - -/** - * 电信/联通获取一键登录Token - * @param request 请求参数结构体 - * @param vendorConfig 当前供应商配置信息 - * @param complete 结果回调 - * @abstract 移动的获取登录Token不走这个回调,走弹起授权页的回调 - */ -- (void)getLoginTokenWithRequest:(YTXRequest *)request - vendorConfig:(YTXVendorConfig *)vendorConfig - complete:(void(^)(NSDictionary *response))complete; - -- (void)deleteCacheWithVendorConfigs:(NSArray *)vendorConfigs; - -@end - -NS_ASSUME_NONNULL_END diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Info.plist b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Info.plist deleted file mode 100644 index f8ae68d..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Info.plist and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Modules/module.modulemap b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Modules/module.modulemap deleted file mode 100644 index 2618651..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/Modules/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module YTXOperators { - umbrella header "YTXOperators.h" - export * - - module * { export * } -} diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/PrivacyInfo.xcprivacy b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/PrivacyInfo.xcprivacy deleted file mode 100644 index 0be0921..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,42 +0,0 @@ - - - - - NSPrivacyTracking - - NSPrivacyCollectedDataTypes - - - NSPrivacyCollectedDataType - NSPrivacyCollectedDataTypeOtherDataTypes - NSPrivacyCollectedDataTypeLinked - - NSPrivacyCollectedDataTypeTracking - - NSPrivacyCollectedDataTypePurposes - - NSPrivacyCollectedDataTypePurposeAnalytics - - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - - - diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/YTXOperators b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/YTXOperators deleted file mode 100644 index a742688..0000000 Binary files a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/ios/YTXOperators.framework/YTXOperators and /dev/null differ diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/license.md b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/license.md deleted file mode 100644 index 57d0ce3..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/license.md +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [ Alibaba ] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/package.json b/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/package.json deleted file mode 100644 index 0c0fc7e..0000000 --- a/gym-manage-uniapp/nativeplugins/AliCloud-NirvanaPns/package.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "阿里云号码认证SDK", - "id": "AliCloud-NirvanaPns", - "version": "2.1.9", - "description": "阿里云号码认证SDK", - "_dp_type":"nativeplugin", - "_dp_nativeplugin":{ - "android": { - "plugins": [ - { - "type": "module", - "name": "AliCloud-NirvanaPns", - "class": "com.nirvana.prd.auth.ALiLoginManager" - } - ], - "hooksClass": "", - "integrateType": "aar", - "dependencies": [], - "compileOptions": { - "sourceCompatibility": "1.8", - "targetCompatibility": "1.8" - }, - "abis": [ - "armeabi-v7a","arm64-v8a","x86" - ], - "minSdkVersion": "21", - "useAndroidX": true, - "permissions": [ - "android.permission.INTERNET", - "android.permission.ACCESS_WIFI_STATE", - "android.permission.CHANGE_NETWORK_STATE", - "android.permission.READ_PHONE_STATE", - "android.permission.WRITE_EXTERNAL_STORAGE", - "android.permission.READ_EXTERNAL_STORAGE", - "android.permission.ACCESS_NETWORK_STATE" - ], - "parameters": { - } - }, - "ios": { - "plugins": [ - { - "type": "module", - "name": "AliCloud-NirvanaPns", - "class": "ATAuthSDKModule" - } - ], - "integrateType": "framework", - "hooksClass": "", - "frameworks": [ - "ATAuthSDK.framework", "YTXMonitor.framework", "YTXOperators.framework","Network.framework" - ], - "embedFrameworks": [ - ], - "capabilities": { - "entitlements": { - }, - "plists": { - } - }, - "plists": { - }, - "assets": [ - ], - "privacies": [ - "" - ], - "embedSwift": false, - "deploymentTarget": "9.0", - "validArchitectures": [ - "armv7","arm64","x86_64" - ], - "parameters": { - }, - "resources": [ - "ATAuthSDK.bundle" - ] - } - } -} diff --git a/gym-manage-uniapp/pages.json b/gym-manage-uniapp/pages.json index ce8bd04..e591e70 100644 --- a/gym-manage-uniapp/pages.json +++ b/gym-manage-uniapp/pages.json @@ -1,19 +1,6 @@ { "pages": [ - { - "path": "pages/memberInfo/login", - "style": { - "navigationStyle": "custom", - "navigationBarTitleText": "登录" - } - }, - { - "path": "pages/test/test", - "style": { - "navigationBarTitleText": "测试页面" - } - }, { "path": "pages/index/index", "style": { @@ -25,6 +12,18 @@ } } }, + { + "path": "pages/memberInfo/purchaseCard", + "style": { + "navigationBarTitleText": "购买会员卡" + } + }, + { + "path": "pages/memberInfo/login", + "style": { + "navigationBarTitleText": "登录" + } + }, { "path": "pages/course/index", "style": { @@ -40,7 +39,6 @@ { "path": "pages/memberInfo/memberInfo", "style": { - "navigationStyle": "custom", "navigationBarTitleText": "我的", "app-plus": { "animationType": "fade-in", @@ -203,10 +201,29 @@ } }, { - "path": "pages/memberInfo/purchaseCard", + "path": "pages/memberInfo/cardDetail", + "style": { + "navigationBarTitleText": "会员卡详情" + } + }, + { + "path": "pages/memberInfo/confirmPayment", + "style": { + "navigationBarTitleText": "确认支付" + } + }, + { + "path": "pages/memberInfo/setPayPassword", "style": { "navigationStyle": "custom", - "navigationBarTitleText": "购买会员卡" + "navigationBarTitleText": "设置支付密码" + } + }, + { + "path": "pages/memberInfo/rechargeStoredCard", + "style": { + "navigationStyle": "custom", + "navigationBarTitleText": "储值卡充值" } }, { @@ -289,12 +306,6 @@ "navigationStyle": "custom", "navigationBarTitleText": "消息详情" } - }, - { - "path": "pages/webview/webview", - "style": { - "navigationBarTitleText": "" - } } ], "globalStyle": { diff --git a/gym-manage-uniapp/pages/checkIn/checkIn.vue b/gym-manage-uniapp/pages/checkIn/checkIn.vue index 049b89e..97a1240 100644 --- a/gym-manage-uniapp/pages/checkIn/checkIn.vue +++ b/gym-manage-uniapp/pages/checkIn/checkIn.vue @@ -98,6 +98,7 @@ import { onLoad, onUnload } from '@dcloudio/uni-app' // 引入状态组件(路径与你保持一致) import QrStatus from '@/components/QRCode/StatusCard.vue' import { getQRCode, getMyMemberCards } from '@/api/main.js' +import { getMemberId } from '@/utils/request.js' let image = ref("") let width = ref(0) @@ -212,9 +213,7 @@ import { getQRCode, getMyMemberCards } from '@/api/main.js' }) try { - const memberInfo = uni.getStorageSync('memberInfo') - console.log(memberInfo) - const memberId = memberInfo?.id || memberInfo?.memberId + const memberId = getMemberId() console.log('[签到页面] 会员ID:', memberId) if (!memberId) { diff --git a/gym-manage-uniapp/pages/memberInfo/booking.vue b/gym-manage-uniapp/pages/memberInfo/booking.vue index 1d66abf..bd79181 100644 --- a/gym-manage-uniapp/pages/memberInfo/booking.vue +++ b/gym-manage-uniapp/pages/memberInfo/booking.vue @@ -138,10 +138,10 @@ import { ref, computed } from 'vue' import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue' import { PAGE, navigateToPage, backToMemberCenter } from '@/common/constants/routes.js' import { - loadMemberStore, cancelOngoingBooking, formatUpcomingAlert } from '@/common/memberInfo/store.js' +import { getMemberId } from '@/utils/request.js' import { canCancelBooking, canSigninCourse } from '@/common/memberInfo/bookingStore.js' import { signinGroupCourse, cancelBooking as cancelBookingApi } from '@/api/main.js' @@ -184,8 +184,7 @@ function setActiveTab(tab) { // 签到团课 async function signinCourse(item) { - const store = loadMemberStore() - const memberId = store.memberProfile?.id || store.profile?.id + const memberId = getMemberId() if (!memberId) { uni.showToast({ title: '请先登录', icon: 'none' }) return diff --git a/gym-manage-uniapp/pages/memberInfo/cardDetail.vue b/gym-manage-uniapp/pages/memberInfo/cardDetail.vue new file mode 100644 index 0000000..1032a4c --- /dev/null +++ b/gym-manage-uniapp/pages/memberInfo/cardDetail.vue @@ -0,0 +1,398 @@ + + + + + diff --git a/gym-manage-uniapp/pages/memberInfo/confirmPayment.vue b/gym-manage-uniapp/pages/memberInfo/confirmPayment.vue new file mode 100644 index 0000000..c599059 --- /dev/null +++ b/gym-manage-uniapp/pages/memberInfo/confirmPayment.vue @@ -0,0 +1,1721 @@ + + + + + diff --git a/gym-manage-uniapp/pages/memberInfo/login.vue b/gym-manage-uniapp/pages/memberInfo/login.vue index acfd367..b9dc9bc 100644 --- a/gym-manage-uniapp/pages/memberInfo/login.vue +++ b/gym-manage-uniapp/pages/memberInfo/login.vue @@ -20,48 +20,42 @@ 验证码登录 认证服务由中国移动提供 - - - - + + - - - - - + + - - - + @@ -84,22 +78,7 @@ 本机号码登录 认证服务由中国移动提供 - - - @@ -123,17 +102,14 @@ diff --git a/gym-manage-uniapp/pages/memberInfo/memberCenter.vue b/gym-manage-uniapp/pages/memberInfo/memberCenter.vue index b5fa423..9ec0537 100644 --- a/gym-manage-uniapp/pages/memberInfo/memberCenter.vue +++ b/gym-manage-uniapp/pages/memberInfo/memberCenter.vue @@ -89,6 +89,48 @@ + + + + + + + + 会员卡即将到期 + + + 查看全部 + + + + + + + + + + + + {{ card.name }} + {{ card.validity }} + + + {{ computeRemainingDays(card.validityEnd) }} + 天后到期 + + + + + + + @@ -470,14 +512,18 @@ diff --git a/gym-manage-uniapp/pages/memberInfo/memberInfo.vue b/gym-manage-uniapp/pages/memberInfo/memberInfo.vue index 2756df8..6fdfbb5 100644 --- a/gym-manage-uniapp/pages/memberInfo/memberInfo.vue +++ b/gym-manage-uniapp/pages/memberInfo/memberInfo.vue @@ -14,6 +14,7 @@ - + @@ -59,12 +60,12 @@ import { ref, onMounted } from 'vue' import { onShow } from '@dcloudio/uni-app' import { PAGE, navigateToPage } from '@/common/constants/routes.js' import { - loadMemberStore, getCenterPageData, renewMemberCard, saveMemberStore, getDefaultStore } from '@/common/memberInfo/store.js' +import { getMemberId } from '@/utils/request.js' import { login as miniappLogin, getUserInfo, getMemberDetail, getCheckInStats, updateUserInfo } from '@/api/main.js' import { setToken, getToken, clearToken } from '@/utils/request.js' import MemberInfoHeader from '@/components/memberInfo/MemberInfoHeader.vue' @@ -87,117 +88,79 @@ const loading = ref(false) const hasActiveCard = ref(false) const isLogin = ref(false) -// 页面加载时检查token onMounted(() => { - const token = getToken() - const isLoginStorage = uni.getStorageSync('isLogin') - if (token || isLoginStorage) { + const token = uni.getStorageSync('token') + const loginMember = uni.getStorageSync('loginMemberInfo') + if (token || loginMember) { isLogin.value = true } }) +// 处理访客登录点击(跳转到登录页面) +function handleGuestLogin() { + console.log('[memberInfo] 用户点击登录区域') + uni.navigateTo({ + url: '/pages/memberInfo/login' + }) +} + async function fetchMemberInfo() { if (loading.value) return loading.value = true console.log('[memberInfo] fetchMemberInfo 开始执行') try { - const res = await getUserInfo({ cache: false }) - console.log('[memberInfo] API返回,res =', res) - const apiData = res.data || res - console.log('[memberInfo] apiData =', apiData) - - if (apiData && (apiData.nickname !== undefined || apiData.phone !== undefined || apiData.id !== undefined)) { - console.log('[memberInfo] 收到有效数据,更新store') - const store = loadMemberStore() - // 更新memberProfile - store.memberProfile = { - ...store.memberProfile, + // 先从 loginMemberInfo 获取用户信息 + const loginMember = uni.getStorageSync('loginMemberInfo') + if (loginMember?.userInfo) { + console.log('[memberInfo] 从loginMemberInfo获取用户信息:', loginMember.userInfo) + const apiData = loginMember.userInfo + // 更新userInfo + userInfo.value = { id: apiData.id, name: apiData.nickname || apiData.name, phone: apiData.phone, avatar: apiData.avatar, memberLevel: apiData.memberLevel || '普通会员' } - // 更新profile - store.profile = { - ...store.profile, - id: apiData.id, - name: apiData.nickname || apiData.name, - phone: apiData.phone, - avatar: apiData.avatar, - gender: apiData.gender, - genderDesc: apiData.genderDesc, - birthday: apiData.birthday, - height: apiData.height, - weight: apiData.weight, - hasPhone: apiData.hasPhone, - isSubscribed: apiData.isSubscribed, - memberLevel: apiData.memberLevel || '普通会员' - } - // 获取会员详细信息(会员卡、积分) - try { - const detailRes = await getMemberDetail() - console.log('[memberInfo] getMemberDetail 返回:', JSON.stringify(detailRes, null, 2)) - const detailData = detailRes.data || {} - store.card = detailData.memberCards ? detailData.memberCards[0] || {} : {} - store.cardInfo = { - name: detailData.memberCards?.[0]?.memberCardName || '暂无会员卡', - type: detailData.memberCards?.[0]?.memberCardTypeDesc || '', - remainingTimes: detailData.memberCards?.[0]?.memberCardTotalTimes || 0, - status: detailData.memberCards?.[0]?.memberCardStatusDesc || '' - } - hasActiveCard.value = (detailData.activeCardCount || 0) > 0 - store.stats = { - ...store.stats, - pointsBalance: detailData.pointsBalance || 0 - } - } catch (e) { - console.error('[memberInfo] 获取会员详情失败:', e) - } - // 获取签到统计 - try { - const statsRes = await getCheckInStats() - console.log('[memberInfo] getCheckInStats 返回:', JSON.stringify(statsRes, null, 2)) - const statsData = statsRes.data || {} - store.stats.checkInCount = statsData.totalCount || 0 - } catch (e) { - console.error('[memberInfo] 获取签到统计失败:', e) - store.stats.checkInCount = 0 - } - saveMemberStore(store) - refreshFromStore() - console.log('[memberInfo] store已更新') - } else { - console.log('[memberInfo] 未登录或数据无效,使用默认空数据') - const store = loadMemberStore() - store.memberProfile = {} - store.profile = {} - store.stats.checkInCount = 0 - hasActiveCard.value = false - saveMemberStore(store) - refreshFromStore() } + + // 获取积分信息 + try { + const detailRes = await getMemberDetail() + const detailData = detailRes.data || {} + stats.value = { + ...stats.value, + pointsBalance: detailData.pointsBalance || 0 + } + } catch (e) { + console.error('[memberInfo] 获取积分信息失败:', e) + } + + // 获取签到统计 + try { + const statsRes = await getCheckInStats() + console.log('[memberInfo] getCheckInStats 返回:', JSON.stringify(statsRes, null, 2)) + const statsData = statsRes.data || {} + stats.value.checkInCount = statsData.totalCount || 0 + } catch (e) { + console.error('[memberInfo] 获取签到统计失败:', e) + stats.value.checkInCount = 0 + } + + // 刷新store中的业务数据 + refreshFromStore() + console.log('[memberInfo] fetchMemberInfo 执行完成') } catch (err) { console.error('[memberInfo] 获取会员信息失败:', err) - // 失败时使用默认空数据 - const store = loadMemberStore() - store.memberProfile = {} - store.profile = {} - store.stats.checkInCount = 0 - hasActiveCard.value = false - saveMemberStore(store) - refreshFromStore() } finally { loading.value = false - console.log('[memberInfo] fetchMemberInfo 执行完成') } } function refreshFromStore() { - const store = loadMemberStore() + const store = getDefaultStore() const pageData = getCenterPageData(store) - console.log('[memberInfo] refreshFromStore - pageData.userInfo:', JSON.stringify(pageData.userInfo)) - userInfo.value = pageData.userInfo + console.log('[memberInfo] refreshFromStore - pageData:', JSON.stringify(pageData)) stats.value = pageData.stats cardInfo.value = pageData.cardInfo bookingPreview.value = pageData.bookingPreview @@ -210,13 +173,6 @@ function goUserInfo() { navigateToPage(PAGE.USER_INFO) } -function handleGuestLogin() { - console.log('[memberInfo] 用户点击登录区域') - uni.navigateTo({ - url: '/pages/memberInfo/login' - }) -} - function goMemberCard() { navigateToPage(PAGE.MEMBER_CARD) } @@ -235,9 +191,6 @@ function onRenewCard() { content: '确认续费 90 天?', success: (res) => { if (!res.confirm) return - const store = loadMemberStore() - renewMemberCard(store, 90) - refreshFromStore() uni.showToast({ title: '续费成功', icon: 'success' }) } }) diff --git a/gym-manage-uniapp/pages/memberInfo/purchaseCard.vue b/gym-manage-uniapp/pages/memberInfo/purchaseCard.vue index ce9be6d..67c2808 100644 --- a/gym-manage-uniapp/pages/memberInfo/purchaseCard.vue +++ b/gym-manage-uniapp/pages/memberInfo/purchaseCard.vue @@ -1,7 +1,6 @@ @@ -217,6 +205,7 @@ import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue' import { getUserInfo, updateUserInfo } from '@/api/main.js' import { previewImage, persistChosenImage } from '@/common/memberInfo/media.js' import { maskPhone, normalizePhoneForStore } from '@/common/memberInfo/format.js' +import { getOssUrl, OSS_BASE_URL } from '@/utils/request.js' import { validateName, validatePhoneForRebind, @@ -229,7 +218,8 @@ import { } from '@/common/memberInfo/validate.js' import { backToMemberCenter } from '@/common/constants/routes.js' -const DEFAULT_AVATAR = 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/AvatarEditWrap.png' +const DEFAULT_AVATAR = getOssUrl('/static/headerImg/default.png') +const DEFAULT_NAME = '活氧舱用户' const name = ref('') const phone = ref('') @@ -278,7 +268,7 @@ function mapApiToProfile(apiData) { } } return { - name: apiData.nickname || '', + name: apiData.nickname || DEFAULT_NAME, phone: apiData.phone || '', gender: genderMap[apiData.gender] || 'female', birthday: birthdayVal, diff --git a/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/common/uni-config-center/uni-cloud-verify/config.json b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/common/uni-config-center/uni-cloud-verify/config.json new file mode 100644 index 0000000..5442385 --- /dev/null +++ b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/common/uni-config-center/uni-cloud-verify/config.json @@ -0,0 +1,6 @@ +{ + "provider": "univerify", + "appid": "__UNI__52E2F0D", + "apiKey": "IKsoDGSM9l8pIws9gXtyp4", + "apiSecret": "" +} diff --git a/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/index.js b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/index.js new file mode 100644 index 0000000..e56c77a --- /dev/null +++ b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/index.js @@ -0,0 +1,59 @@ +exports.main = async (event, context) => { + let { access_token, openid, appid } = event + + if (event.body) { + try { + const body = typeof event.body === 'string' ? JSON.parse(event.body) : event.body + access_token = body.access_token || body.accessToken || access_token + openid = body.openid || openid + appid = body.appid || appid + } catch (e) { + console.error('解析body失败:', e) + } + } + + if (!access_token) { + return { + success: false, + message: 'access_token不能为空' + } + } + + try { + const params = { + provider: 'univerify', + access_token: access_token, + openid: openid + } + + if (appid) { + params.appid = appid + } + + console.log('调用getPhoneNumber参数:', JSON.stringify(params)) + + const res = await uniCloud.getPhoneNumber(params) + + console.log('getPhoneNumber返回:', JSON.stringify(res)) + + if (res && res.phoneNumber) { + return { + success: true, + phone: res.phoneNumber + } + } else { + return { + success: false, + message: '获取手机号失败', + error: res + } + } + } catch (error) { + console.error('获取手机号异常:', error) + return { + success: false, + message: '获取手机号异常', + error: error.message || error + } + } +} diff --git a/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/package.json b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/package.json new file mode 100644 index 0000000..3e6e7a3 --- /dev/null +++ b/gym-manage-uniapp/uniCloud-aliyun/cloudfunctions/getPhoneByUniverify/package.json @@ -0,0 +1,12 @@ +{ + "name": "getPhoneByUniverify", + "version": "1.0.0", + "description": "通过univerify获取手机号", + "main": "index.js", + "extensions": { + "uni-cloud-verify": {} + }, + "cloudfunction-config": { + "path": "/getPhoneByUniverify" + } +} diff --git a/gym-manage-uniapp/uniCloud-aliyun/database/JQL查询.jql b/gym-manage-uniapp/uniCloud-aliyun/database/JQL查询.jql new file mode 100644 index 0000000..35d21de --- /dev/null +++ b/gym-manage-uniapp/uniCloud-aliyun/database/JQL查询.jql @@ -0,0 +1,12 @@ +// 本文件用于,使用JQL语法操作项目关联的uniCloud空间的数据库,方便开发调试和远程数据库管理 +// 编写clientDB的js API(也支持常规js语法,比如var),可以对云数据库进行增删改查操作。不支持uniCloud-db组件写法 +// 可以全部运行,也可以选中部分代码运行。点击工具栏上的运行按钮或者按下【F5】键运行代码 +// 如果文档中存在多条JQL语句,只有最后一条语句生效 +// 如果混写了普通js,最后一条语句需是数据库操作语句 +// 此处代码运行不受DB Schema的权限控制,移植代码到实际业务中注意在schema中配好permission +// 不支持clientDB的action +// 数据库查询有最大返回条数限制,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-database.html#limit +// 详细JQL语法,请参考:https://uniapp.dcloud.net.cn/uniCloud/jql.html + +// 下面示例查询uni-id-users表的所有数据 +db.collection('uni-id-users').get(); diff --git a/gym-manage-uniapp/uni_modules/uni-config-center/changelog.md b/gym-manage-uniapp/uni_modules/uni-config-center/changelog.md new file mode 100644 index 0000000..57dbcb5 --- /dev/null +++ b/gym-manage-uniapp/uni_modules/uni-config-center/changelog.md @@ -0,0 +1,6 @@ +## 0.0.3(2022-11-11) +- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug +## 0.0.2(2021-04-16) +- 修改插件package信息 +## 0.0.1(2021-03-15) +- 初始化项目 diff --git a/gym-manage-uniapp/uni_modules/uni-config-center/package.json b/gym-manage-uniapp/uni_modules/uni-config-center/package.json new file mode 100644 index 0000000..bace866 --- /dev/null +++ b/gym-manage-uniapp/uni_modules/uni-config-center/package.json @@ -0,0 +1,81 @@ +{ + "id": "uni-config-center", + "displayName": "uni-config-center", + "version": "0.0.3", + "description": "uniCloud 配置中心", + "keywords": [ + "配置", + "配置中心" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "type": "unicloud-template-function" + }, + "directories": { + "example": "../../../scripts/dist" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "u" + } + } + } + } +} diff --git a/gym-manage-uniapp/uni_modules/uni-config-center/readme.md b/gym-manage-uniapp/uni_modules/uni-config-center/readme.md new file mode 100644 index 0000000..03f7fc2 --- /dev/null +++ b/gym-manage-uniapp/uni_modules/uni-config-center/readme.md @@ -0,0 +1,93 @@ +# 为什么使用uni-config-center + +实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ ├─index.js + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b // plugin-b对应的目录 + ├─index.js + └─config.json // plugin-b对应的配置文件 +``` + +假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。 + +uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下 + +```bash +cloudfunctions +└─────common 公共模块 + ├─plugin-a // 插件A对应的目录 + │ └─index.js + ├─plugin-b // plugin-b对应的目录 + │ └─index.js + └─uni-config-center + ├─index.js // config-center入口文件 + ├─plugin-a + │ ├─config.json // plugin-a对应的配置文件 + │ └─other-file.cert // plugin-a依赖的其他文件 + └─plugin-b + └─config.json // plugin-b对应的配置文件 +``` + +使用uni-config-center后的优势 + +- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便 +- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持) + +# 用法 + +在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common) + +```js +const createConfig = require('uni-config-center') + +const uniIdConfig = createConfig({ + pluginId: 'uni-id', // 插件id + defaultConfig: { // 默认配置 + tokenExpiresIn: 7200, + tokenExpiresThreshold: 600, + }, + customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并 + // defaudltConfig 默认配置 + // userConfig 用户配置 + return Object.assign(defaultConfig, userConfig) + } +}) + + +// 以如下配置为例 +// { +// "tokenExpiresIn": 7200, +// "passwordErrorLimit": 6, +// "bindTokenToDevice": false, +// "passwordErrorRetryTime": 3600, +// "app-plus": { +// "tokenExpiresIn": 2592000 +// }, +// "service": { +// "sms": { +// "codeExpiresIn": 300 +// } +// } +// } + +// 获取配置 +uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象 +uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200 +uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300 +uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600 + +// 获取文件绝对路径 +uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径 + +// 引用文件(require) +uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。 + +// 判断是否包含某文件 +uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在 +``` \ No newline at end of file diff --git a/gym-manage-uniapp/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js b/gym-manage-uniapp/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js new file mode 100644 index 0000000..00ba62f --- /dev/null +++ b/gym-manage-uniapp/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js @@ -0,0 +1 @@ +"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=vt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=vt(p,"Map"),J=vt(Object,"create"),K=function(){function t(){}return function(r){if(!xt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r-1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=_t(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return _t(this,t).get(t)},Y.prototype.has=function(t){return _t(this,t).has(t)},Y.prototype.set=function(t,r){var e=_t(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return Ct(t)&&ct(t)==o}function ft(t){return!(!xt(t)||function(t){return!!U&&U in t}(t))&&(zt(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!xt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=yt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),xt(i))!function(t,r,e,n,o,i,u){var a=gt(t,e),f=gt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=Ot(f),_=!p&&At(f),v=!p&&!_&&Ft(f);l=f,p||_||v?Ot(a)?l=a:Ct(j=a)&&mt(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e-1&&t%1==0&&t0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(pt);function jt(t,r){return t===r||t!=t&&r!=r}var wt=at(function(){return arguments}())?at:function(t){return Ct(t)&&F.call(t,"callee")&&!B.call(t,"callee")},Ot=Array.isArray;function mt(t){return null!=t&&Mt(t.length)&&!zt(t)}var At=G||function(){return!1};function zt(t){if(!xt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function Mt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function xt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function Ct(t){return null!=t&&"object"==typeof t}var Ft=b?function(t){return function(r){return t(r)}}(b):function(t){return Ct(t)&&Mt(t.length)&&!!s[ct(t)]};function Ut(t){return mt(t)?tt(t,!0):st(t)}var St,It=(St=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=St.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!xt(e))return!1;var n=typeof r;return!!("number"==n?mt(e)&&dt(r,e.length):"string"==n&&r in e)&&jt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++ec.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){if(!this._config){const t=this._getUserConfig();this._config=Array.isArray(t)?t:(this.customMerge||u)(this.defaultConfig,t)}let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;tparseInt(e)):void 0}function o(e,n){const i=r(e),t=r(n);return i?t?function(e,n){const i=Math.max(e.length,n.length);for(let t=0;tr)return 1;if(i=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");n>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${n}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:i.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:i.ACCOUNT_BANNED};case 2:throw{errCode:i.ACCOUNT_AUDITING};case 3:throw{errCode:i.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:i.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:i.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:i.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const n=await T.where({role_id:I.in(e)}).get(),i=(t=n.data.reduce((e,n)=>(n.permission&&e.push(...n.permission),e),[]),Array.from(new Set(t)));var t;return this.userPermission={role:e,permission:i},this.userPermission}async _createToken({uid:e,role:n,permission:t}={}){if(!n||!t){const e=await this.getUserPermission();n=e.role,t=e.permission}let r={uid:e,role:n,permission:t};if(this.uniId.interceptorMap.has("customToken")){const i=this.uniId.interceptorMap.get("customToken");if("function"!=typeof i)throw new Error("Invalid custom token file");r=await i({uid:e,role:n,permission:t})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.19"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const n=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*n.iat)return!1}catch(e){if(e.errCode===i.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:n,permission:t}={}){if(!e)throw{errCode:i.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:n,permission:t});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:i.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const n=this._checkToken(e);this.uid=n.uid,this.oldTokenPayload=n;const{uid:t}=n,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:t,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:n}=this.config;let t;try{t=k(e,n)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:i.TOKEN_EXPIRED};throw{errCode:i.CHECK_TOKEN_FAILED}}return t}async checkToken(e,{autoRefresh:n=!0}={}){if(!e)throw{errCode:i.CHECK_TOKEN_FAILED};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=t,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:n}=await this.getUserPermission();a.role=e,a.permission=n}if(!r||!n){const e={code:0,errCode:0,...t,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*t.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...t,...a,...d};return delete l.uniIdVersion,l}}var E=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:n=!0}={}){return new m({uniId:this}).checkToken(e,{autoRefresh:n})},createToken:async function({uid:e,role:n,permission:i}={}){return new m({uniId:this}).createToken({uid:e,role:n,permission:i})},refreshToken:async function({token:e}={}){return new m({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:n,config:i}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):n,this._config=i,this.config=this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,n){this.interceptorMap.set(e,n)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(this._config)return this._config;if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let n;switch(["app-plus","app-android","app-ios"].indexOf(this._clientInfo.platform)>-1&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":n="h5";break;case"app":n="app-plus"}const i=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];n&&e[n]&&i.push(e[n]),i.push(e[this._clientInfo.platform]);const t=Object.assign(...i);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!t||!t[e])throw new Error(`Config parameter missing, ${e} is required, please check your config file uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json`)}),t}_getConfig(){return this._getPlatformConfig()}}for(const e in E)x.prototype[e]=E[e];function y(e){const n=new x(e);return new Proxy(n,{get(e,n){if(n in e&&0!==n.indexOf("_")){if("function"==typeof e[n])return(i=e[n],function(){let e;try{e=i.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return t(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==n&&"config"!==n)return e[n]}var i}})}x.prototype.createInstance=y;const O={createInstance:y};module.exports=O; diff --git a/gym-manage-uniapp/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json b/gym-manage-uniapp/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json new file mode 100644 index 0000000..37b425a --- /dev/null +++ b/gym-manage-uniapp/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json @@ -0,0 +1,20 @@ +{ + "name": "uni-id-common", + "version": "1.0.19", + "description": "uni-id token生成、校验、刷新", + "main": "index.js", + "homepage": "https:\/\/uniapp.dcloud.io\/uniCloud\/uni-id-common.html", + "repository": { + "type": "git", + "url": "git+https:\/\/gitee.com\/dcloud\/uni-id-common.git" + }, + "author": "DCloud", + "license": "Apache-2.0", + "dependencies": { + "uni-config-center": "file:..\/..\/..\/..\/..\/uni-config-center\/uniCloud\/cloudfunctions\/common\/uni-config-center" + }, + "origin-plugin-dev-name": "uni-id-common", + "origin-plugin-version": "1.0.19", + "plugin-dev-name": "uni-id-common", + "plugin-version": "1.0.19" +} \ No newline at end of file diff --git a/gym-manage-uniapp/utils/request.js b/gym-manage-uniapp/utils/request.js index fe3bf5f..09809c9 100644 --- a/gym-manage-uniapp/utils/request.js +++ b/gym-manage-uniapp/utils/request.js @@ -1,7 +1,32 @@ -const BASE_URL = '/api' -// const BASE_URL = 'http://localhost:8084' +// const BASE_URL = '/api' +const BASE_URL = 'http://192.168.43.89:8084/api' -// 缓存相关常`量 +// OSS 静态资源基础地址 +export const OSS_BASE_URL = 'https://gymfuture.oss-cn-chengdu.aliyuncs.com' + +/** + * 获取 OSS 资源完整地址 + * @param {string} path - OSS 资源路径,如 '/static/images/camera.png' + * @returns {string} 完整 OSS 地址 + */ +export const getOssUrl = (path) => { + if (!path) return '' + if (path.startsWith('http://') || path.startsWith('https://')) { + return path + } + return OSS_BASE_URL + path +} + +/** + * 获取当前登录会员ID + * @returns {number|null} 会员ID,未登录返回null + */ +export const getMemberId = () => { + const loginMember = uni.getStorageSync('loginMemberInfo') + return loginMember?.id || loginMember?.memberId || null +} + +// 缓存相关常量 const CACHE_PREFIX = 'API_CACHE_' const CACHE_EXPIRE_TIME = 5 * 60 * 1000 // 默认缓存时间5分钟 @@ -221,11 +246,11 @@ export const request = (options) => { console.log(`[API] 响应头:`, res.header) console.log(`[API] 响应数据:`, JSON.stringify(res.data, null, 2)) - if (res.statusCode === 200) { + if (res.statusCode === 200 || res.statusCode === 204) { if (cache && cacheKey && res.data) { setCache(cacheKey, res.data, cacheTime) } - resolve(res.data) + resolve(res.data || {}) } else if (res.statusCode === 401) { clearToken() uni.showToast({ @@ -255,7 +280,9 @@ export const requestUtils = { getCache, setCache, clearCache, - clearAllCache + clearAllCache, + OSS_BASE_URL, + getOssUrl } // 添加便捷方法