diff --git a/.env.development b/.env.development index 3cd434a5..136e3641 100644 --- a/.env.development +++ b/.env.development @@ -6,7 +6,7 @@ ENV = 'development' # VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001' -VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001' +#VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001' # VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002' @@ -15,7 +15,7 @@ VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001' # VITE_APP_BASE_API_Url = 'http://aitscdn.jlbank.com.cn:7001' # VITE_APP_BASE_API_Url = 'http://192.168.108.129' # dev -#VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001' +VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001' # sit diff --git a/src/components/points-and-badge/badge.vue b/src/components/points-and-badge/badge.vue index c6823583..3714a459 100644 --- a/src/components/points-and-badge/badge.vue +++ b/src/components/points-and-badge/badge.vue @@ -56,7 +56,7 @@ const popup = ref(null); const current = ref(0); const opacity = ref(1); -let CloseComplete + let CloseComplete const badgesList = ref([]); const pointsList = ref([]); const multiple = computed(() => badgesList.value.length > 1); diff --git a/src/components/points-and-badge/check-in.vue b/src/components/points-and-badge/check-in.vue index ac5a731d..cb19ed5d 100644 --- a/src/components/points-and-badge/check-in.vue +++ b/src/components/points-and-badge/check-in.vue @@ -82,6 +82,9 @@ const customStyle = { borderRadius: '40rpx' //圆角 }; + let checkInClickCallback; + let checkInSuccessCallback; + const dateGroups = ref([]); const expand = ref(false); // 展开状态 const isSigned = ref(false); // 今日签到状态 @@ -103,37 +106,32 @@ // 退出签到 const close = () => { popup.value.close(); + typeof checkInClickCallback === 'function' && checkInClickCallback({ + status:false + }) }; const checkInLoading = ref(false); // 签到 const checkIn = () => { if (checkInLoading.value) return; checkInLoading.value = true; - addPointsByCheckIn({ days: continuousDay.value }) - .then((res) => { - console.log('签到结果', res); + // 函数执行成功的回调 + checkInClickCallback({ + status:true, + days: continuousDay.value, + successCb: ({ days, res }) => { + console.log('签到成功', res); checkInLoading.value = false; isSigned.value = true; - continuousDay.value = continuousDay.value + 1; - // common.msg('签到成功,请明日继续!') - emits( - 'checkInFun', - true, - res.body.points, - res.body.pointsBadges, - // [{ changePoints: 5 }], - // [ - // { - // pointsBadgeImg: '/traoss/tras3/show/S3F0250181220722025110713501700000661177', - // pointsBadgeName: '黄金徽章' - // } - // ] - ); - }) - .catch((err) => { + continuousDay.value = days; + checkInSuccessCallback(true, days, res.body.points, res.body.pointsBadges); + }, + failCb: (res) => { checkInLoading.value = false; + console.log('签到失败', res); common.msg('签到失败,请稍后再试'); - }); + } + }); }; /** @@ -207,17 +205,19 @@ return groupedList; } - - const open = (checkInToday, days) => { - isSigned.value = checkInToday === 'Y' ? true : false; // 今日签到状态 - // isSigned.value = false; // 今日签到状态 + + const open = (isSignedStatus, days, onCheckInClick = () => {}, onCheckInSuccess = () => {}) => { + console.log('isSignedStatus', isSignedStatus); + isSigned.value = isSignedStatus; // 今日签到状态 continuousDay.value = days; // 连续签到 + checkInClickCallback = onCheckInClick; + checkInSuccessCallback = onCheckInSuccess; // 示例:X=10时,以"10天前"为第1天,生成35天列表 try { const X = continuousDay.value - (isSigned.value ? 1 : 0); // const X = 10; - console.log(`以${continuousDay.value}天`); - console.log(`以${X}天前为第1天的35天分组日期:`); + // console.log(`以${continuousDay.value}天`); + // console.log(`以${X}天前为第1天的35天分组日期:`); dateGroups.value = generateGroupedDateList(X); } catch (err) { console.error(err.message); diff --git a/src/composables/useCheckIn.js b/src/composables/useCheckIn.js index 9fd831cd..67a8d5bd 100644 --- a/src/composables/useCheckIn.js +++ b/src/composables/useCheckIn.js @@ -1,16 +1,226 @@ -import { queryCheckIn } from '@/api/pointsAndRank.js'; +import { + queryCheckIn, + addPointsByCheckIn +} from '@/api/pointsAndRank.js'; import common from '@/common/common'; - +import { + getUserInfo +} from '@/common/common'; +import { + ref +} from 'vue'; export default function useCheckIn() { + const checkInRef = ref(null) + // ========== 核心工具方法 ========== + /** + * 获取当前用户的签到存储key(区分不同用户) + */ + const getKey = () => { + const userInfo = getUserInfo(); + const userId = userInfo?.userId || ''; // 修复原代码userId重复赋值问题 + if (!userId) { + console.warn('用户ID为空,无法获取签到状态'); + return ''; + } + return `${userId}_user_sign_in_status`; + }; + + /** + * 获取今日日期(YYYY-MM-DD) + */ + const getTodayDate = () => { + const now = new Date(); + return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`; + }; + + /** + * 读取本地存储的签到状态 + * @returns {Object} { isSigned: boolean, signDate: string } + */ + const getLocalSignStatus = () => { + const key = getKey(); + if (!key) return { + signDate: '', + checkInDays: 0, + PopupDay: '' + }; + try { + // 读取本地存储的签到信息(兼容JSON格式) + const rawData = common.getValue(key); + if (!rawData) return { + signDate: '', + checkInDays: 0, + popupDay: '' + }; + + // 兼容存储的是字符串或JSON对象的情况 + const signStatus = rawData; + return { + signDate: signStatus.signDate || '', + checkInDays: signStatus.checkInDays || 0, + popupDay: signStatus.popupDay || '', + + }; + } catch (e) { + console.error('读取本地签到状态失败', e); + return { + signDate: '', + checkInDays: 0, + popupDay: '' + }; + } + }; + + /** + * 更新本地签到状态(支持按需更新字段) + * @param {boolean|undefined} isSigned - 是否签到(可选,传入则更新) + * @param {number|undefined} checkInDays - 签到天数(可选,传入则更新) + * @param {string|undefined} popupDay - 弹窗关闭日期(可选,传入则更新) + */ + const setLocalSignStatus = (isSigned, checkInDays, popupDay) => { + const key = getKey(); + if (!key) return; + + // 1. 读取本地原有数据(若无则初始化空对象) + let oldSignStatus = {}; + try { + oldSignStatus = common.getValue(key) || {}; // 兼容common.getValue返回null/undefined的情况 + } catch (e) { + console.warn('读取原有签到状态失败,使用空对象初始化', e); + oldSignStatus = {}; + } + + // 2. 初始化新状态:先继承原有数据 + const newSignStatus = { ...oldSignStatus }; + + // 3. 按需更新字段(仅当参数传入时覆盖) + // 处理isSigned:传入则更新,且为true时自动设置signDate + if (isSigned !== undefined) { + // 保持原有逻辑:isSigned为true时,signDate设为今日 + newSignStatus.signDate = isSigned ? getTodayDate() : oldSignStatus.signDate; + } + + // 处理checkInDays:传入则更新,未传入保留原有值 + if (checkInDays !== undefined) { + newSignStatus.checkInDays = checkInDays; + } + + // 处理popupDay:传入非空则更新,未传入/空值保留原有值 + if (popupDay !== undefined) { + newSignStatus.popupDay = popupDay? getTodayDate() : oldSignStatus.popupDay; + } + + // 4. 重新存入本地(覆盖原有数据) + try { + console.log('存入的数据(原有+更新)', newSignStatus); + common.setValue(key, newSignStatus); + } catch (e) { + console.error('更新本地签到状态失败', e); + } + }; + + + + // ========== 对外暴露的核心方法 ========== + /** + * 初始化签到状态(页面加载时调用,同步本地与后端状态) + * @returns {Promise<{ isSigned: boolean, checkInDays?: number }>} 签到状态 + 连续签到天数 + */ + const initCheckInStatus = async (complete = () => {}) => { + const today = getTodayDate(); + const localStatus = getLocalSignStatus(); + console.log('localStatus', localStatus); + // 1. 本地已有今日签到记录 → 直接返回本地状态 + if (localStatus.signDate === today) { + + complete(true, localStatus.checkInDays, localStatus.popupDay === today) + return true; + } + // 2. 本地记录过期/无记录 → 请求接口获取最新状态 + try { + const res = await queryCheckIn(); // 调用查询签到状态接口 + const { + body + } = res || {}; + console.log('bodbodyy', body); + // // 接口返回格式适配(根据实际后端返回调整) + const isSigned = body?.checkInToday === 'Y'; + const checkInDays = body?.days || 0; + setLocalSignStatus(isSigned, checkInDays); + // if (!isSigned) { // 没签到执行签到弹窗 + // console.log('没签到执行签到弹窗'); + // //如果今日点击过x那么久不弹了 + // // if(localStatus.popupDay === today) return; + // complete(isSigned, checkInDays, localStatus.popupDay === today) + // } + complete(isSigned, checkInDays, localStatus.popupDay === today) + + } catch (e) { + console.error('请求签到状态接口失败', e); + } + }; + + /** + * 判断今日是否已签到(简化版,供快速判断) + * @returns {boolean} + */ const getTodayCheckInStatus = () => { - // common.getValue() - } - // 获取今日是否签到消息 - const getCheckInInfo = () => { - // todo 后续加防止重复多次请求逻辑 - queryCheckIn().then(({ body }) => { - user_info.checkInToday = body.checkInToday; // 今日是否签到 - user_info.checkInDays = body.days; // 连续签到天数 - }); + const localStatus = getLocalSignStatus(); + const today = getTodayDate(); + // 日期匹配且已签到,才返回true + return localStatus.signDate === today; + }; + + + + /** + * 执行签到操作(核心方法) + * @param {Function} successCb - 签到成功回调 + * @param {Function} failCb - 签到失败回调 + * @returns {Promise} 签到是否成功 + */ + const checkInFun = async ({ + status, + days=0, + successCb=() =>{}, + failCb=() =>{} + }) => { + if(!status) { // 点击了关闭 + console.log('点击了关闭'); + + setLocalSignStatus(undefined, undefined, true); + return; + } + console.log('请求接口', days); + addPointsByCheckIn({ + days + }) + .then((res) => { + console.log('接口成功回调', res); + setLocalSignStatus(true, days + 1); + successCb?.({ + days: days + 1, + res + }); + }).catch((error) => { + failCb?.(error) + }) + }; + + /** + * 重置签到状态(可选,用于特殊场景) + */ + const resetCheckInStatus = () => { + const key = getKey(); + if (key) common.removeValue(key); // 需确保common有remove方法,无则补充 + }; + + // ========== 返回对外暴露的方法 ========== + return { + checkInRef, + initCheckInStatus, // 初始化签到状态(页面加载时调用) + checkInFun, // 执行签到 + getLocalSignStatus, // 获取签到缓存信息 + getTodayCheckInStatus // 获取今天签到状态 }; } \ No newline at end of file diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index ab11b621..95a3dc9a 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -6,8 +6,15 @@ - + @@ -24,9 +31,16 @@ - + 消息 @@ -58,38 +72,54 @@ 本年学习时长 - + h 本年陪练次数 - + 本年考试次数 - + - + AI学习 - + AI问答 @@ -127,7 +157,6 @@ - @@ -158,7 +158,7 @@ @cancel="avatarOnCancel" @confirm="avatarOnConfirm" > - + @@ -183,8 +183,10 @@ import checkIn from '@/components/points-and-badge/check-in'; import badge from '@/components/points-and-badge/badge'; import points from '@/components/points-and-badge/points'; + import useCheckIn from '@/composables/useCheckIn'; import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge'; const { handlePointsBadgePopup, badgeRef, pointsRef } = usePointsAndBadge(); + const { checkInRef, checkInFun, initCheckInStatus } = useCheckIn(); const { avatarCropperUrl, click_update_avatar, avatarCropperStatus, avatarOnCancel, avatarOnConfirm } = useUpdateAvatar({ success: (userData) => { user_info.imageAddr = userData.imageAddr; @@ -194,30 +196,32 @@ const currentIndex = ref(0); const socketStore = useSocketStore(); const badgeNumRef = ref(null); - const checkInRef = ref(null); - const currentPointsRef = ref(null); - + const gotoTestPage = () => { + common.navigateTo('/pages/test/index'); + }; const user_info = reactive({ userName: '', userId: '', imageAddr: '', loginName: '', - checkInToday: '', // 今日是否签到 - checkInDays: 0 // 连续签到天数 + checkInToday: 0, // 今日是否签到 0未知, 1签到,2未签到 + checkInDays: 0 }); // 签到打开 const checkInClick = () => { - checkInRef.value.open(user_info.checkInToday, user_info.checkInDays); + checkInRef.value.open( + user_info.checkInToday === 1, + user_info.checkInDays, + checkInFun, + (status, days, pointsList = [], badgesList = []) => { + user_info.checkInToday = status ? 1 : 2; + user_info.checkInDays = days; + handlePointsBadgePopup(pointsList, badgesList); + } + ); }; - // 签到成功回调 - const checkInFun = (status, pointsList = [], badgesList = []) => { - if (status) { - getCheckInInfo(); - } - handlePointsBadgePopup(pointsList, badgesList) - }; - + const click_loginout = () => { common.show('确定退出登录?').then(async (res) => { if (!res) return; @@ -285,7 +289,6 @@ if (currentPoints !== this.currentPoints) { this.startCurrentPoints = this.currentPoints; this.currentPoints = currentPoints; - console.log('this.startCurrentPointsx', this.startCurrentPoints, this.currentPoints); currentPointsRef.value.start(); } } catch (error) { @@ -294,15 +297,7 @@ } } }); - - // 获取今日是否签到消息 - const getCheckInInfo = () => { - // todo 后续加防止重复多次请求逻辑 - queryCheckIn().then(({ body }) => { - user_info.checkInToday = body.checkInToday; // 今日是否签到 - user_info.checkInDays = body.days; // 连续签到天数 - }); - }; + onLoad(() => { statistics_data['init'](); // 初始化数据 }); @@ -311,7 +306,10 @@ Object.assign(user_info, getUserInfo()); statistics_data['get_statistics_data'](); // 获取统计数据 // 获取今日是否签到消息 - getCheckInInfo(); + initCheckInStatus((isSigned, checkInDays, popUpStatus) => { + user_info.checkInToday = isSigned ? 1 : 2; + user_info.checkInDays = checkInDays; + }); }); onHide(() => { checkInRef.value && checkInRef.value.close();