开发积分兑换

This commit is contained in:
田岩
2025-11-20 15:48:56 +08:00
parent 42a34226a8
commit eae888d7c9
9 changed files with 192 additions and 97 deletions
+4 -5
View File
@@ -5,17 +5,16 @@ ENV = 'development'
# VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_API_Url = 'http://192.168.247.200'
# 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
# VITE_APP_BASE_API_Url = 'http://25.18.122.91:9786'
# UAT
# VITE_APP_BASE_API_Url = 'http://25.18.122.78:9786'
@@ -31,11 +30,11 @@ VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
#VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.91:9786'
# VITE_APP_BASE_H5_API_Url = 'http://25.18.122.78:9786'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://192.168.247.200'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.32.158:9601'
# VITE_APP_BASE_H5_API_Url_TEST = 'http://127.0.0.1:5000'
#VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://192.168.247.200'
# VITE_APP_BASE_H5_API_Url_TRAEXAM = 'http://192.168.247.200'
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.32.154:9605'
+2 -2
View File
@@ -64,8 +64,8 @@ let CloseComplete
const title = computed(() =>
badgesList.value.length === 1
? '恭喜你获得徽章'
: `恭喜你获得${titleNumberText[badgesList.value.length - 1]}徽章`
? '恭喜你获得徽章'
: `恭喜你获得${titleNumberText[badgesList.value.length - 1]}枚徽章`
);
const buttonColor = 'linear-gradient( 270deg, #F81758 0%, #FFA062 100%)';
const customStyle = {
+9 -4
View File
@@ -99,9 +99,14 @@
</template>
<uni-popup ref="popupRef" class="popup">
<view class="sheet_popup_div">
<view class="title_div">双人对战规则说明</view>
<view class="title_div">
规则说明
<view class="title_back_icon" @click="popupRef.close()">
<image class="img" :src="optionErrorIcon('#333')"></image>
</view>
</view>
<view class="note_div">
{{ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'|| data_info.ruleDesc }}
{{ data_info.ruleDesc }}
</view>
</view>
</uni-popup>
@@ -117,10 +122,10 @@
import { queryTraCompetitionInfoByPkUser } from '@/api/competition';
import { onLoad } from '@dcloudio/uni-app';
import { defaultAnonymousAvatar } from '@/enum';
import { pkAnonymousClose, pkAnonymousOpen, pkRankingList, pkRules, switchIcon } from '@/common/imgSvg';
import { pkAnonymousClose, pkAnonymousOpen, pkRankingList, pkRules, switchIcon, optionErrorIcon } from '@/common/imgSvg';
import { queryTraUserAnonyByUserId, updateTraUserAnony } from '@/api/user';
import selectionInstitutions from '@/components/selection-institutions/index.vue';
import { nextTick } from 'process';
const data_info = reactive({
userId: '',
+16 -2
View File
@@ -412,7 +412,16 @@
// console.log('倒计时时间', practiceRemainingTime.value);
// Pk时间到
if (practiceRemainingTime.value <= 0) {
console.log('Pk时间到,带走的数据', pkData);
common.setPageCache('competition_pk_to_resulf', pkData);
if (practiceTimeTimer) {
clearInterval(practiceTimeTimer);
}
nextTick(() => {
common.redirectTo(
`/pages/competition/result?mode=${mode}&execId=${pkData.execId}&orgId=${pkData.orgId}&papersId=${pkData.papersId}`
);
});
}
}, 1000);
@@ -425,7 +434,6 @@
return;
}
Object.assign(pkData, pkDataParams);
console.log('pkData', pkData);
pkDataParams.qnsInfoVos.forEach((res) => {
topicList.push({
...res,
@@ -446,6 +454,12 @@
onMounted(() => {
startTimer(); // 启动/恢复定时器
});
onUnmounted(() => {
// 卸载定时器
if (practiceTimeTimer) {
clearInterval(practiceTimeTimer);
}
})
onBackPress((res) => res.from === 'backbutton');
</script>
+3 -2
View File
@@ -37,7 +37,7 @@
:src="item.ossAddr"
mode="aspectFit"
></image-preview>
<image v-else class="avatar-image" :src="defaultAvatarSrc"></image>
<image v-else class="avatar-image" :src="defaultAnonymousAvatar"></image>
</view>
<view class="user-name">
{{ item.isAnony === 'N' ? item.userName : formatName(item.userName) }}
@@ -66,7 +66,7 @@
:src="userRankObj.ossAddr"
mode="aspectFit"
></image-preview>
<image class="avatar-image" v-else :src="defaultAvatarSrc"></image>
<image class="avatar-image" v-else :src="defaultAnonymousAvatar"></image>
</view>
<view class="user-name">{{ userRankObj.isAnony === 'N' ? userRankObj.userName : formatName(userRankObj.userName) }}</view>
<view class="user-org">{{ userRankObj.orgName }}</view>
@@ -87,6 +87,7 @@
import { formatSecondsToMS } from './js/tool';
import { ref } from 'vue';
import { formatName } from '@/common/common';
import { defaultAnonymousAvatar } from '@/enum';
const papersId = ref('');
const orgId = ref('');
const userList = ref([]);
+52 -36
View File
@@ -37,7 +37,9 @@
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
</view>
<view class="name-div">{{ pkData.isAnony === 'N' ?pkData.userName:formatName(pkData.userName) }}</view>
<view class="name-div">
{{ pkData.isAnony === 'N' ? pkData.userName : formatName(pkData.userName) }}
</view>
<view class="title">正确/总题数</view>
<view class="topic-div number">
<text class="loadingNoText font-size-54">{{ pkData.correctNub }}</text>
@@ -60,7 +62,9 @@
<image-preview v-if="pkData.pkIsAnony === 'N'" class="img" :src="pkData.imgPk"></image-preview>
<image v-else class="img" :src="defaultAnonymousAvatar" mode="aspectFill"></image>
</view>
<view class="name-div">{{ pkData.pkIsAnony === 'N' ? pkData.userNamePk : formatName(pkData.userNamePk) }}</view>
<view class="name-div">
{{ pkData.pkIsAnony === 'N' ? pkData.userNamePk : formatName(pkData.userNamePk) }}
</view>
<view class="title">正确/总题数</view>
<view class="topic-div number">
<text class="loadingNoText font-size-54">{{ pkData.correctNubPk }}</text>
@@ -81,7 +85,7 @@
</view>
<!-- 查看排行榜按钮 -->
<view class="ranking-list-div" @click="buttonClick('toRanking')">
<text v-if="mode==='pk_in'">查看排行榜</text>
<text v-if="mode === 'pk_in'">查看排行榜</text>
</view>
<!-- 下方的两个按钮 -->
<view class="fl1"></view>
@@ -131,8 +135,8 @@
totalScore: 0, // 我方总分 int
// 对方的
userIdPk: '', // 用户Id String
userNamePk: '', // 用户姓名 String
userIdPk: '', // 对方用户Id String
userNamePk: '', // 对方用户姓名 String
imgPk: '', // 对方头像 String
pkIsAnony: '', // 匿名 String
correctNubPk: 0, // 正确数 int
@@ -146,8 +150,7 @@
common.navigateBack(2);
} else if (type === 'continue') {
common.navigateBack();
} else if (type === 'toRanking' && mode.value ==='pk_in') {
} else if (type === 'toRanking' && mode.value === 'pk_in') {
common.navigateTo(`/pages/competition/ranking?papersId=${pkData.papersId}&orgId=${pkData.orgId}`);
}
};
@@ -160,43 +163,56 @@
const pkDataInit = common.getPageCache('competition_pk_to_resulf');
const userInfo = getUserInfo();
console.log('userInfo', userInfo);
console.log('pkDataInit', pkDataInit);
Object.assign(pkData, {
userName: userInfo.userName,
userName: pkDataInit.userName ?? '',
isAnony: pkDataInit.isAnony ?? '',
pkIsAnony: pkDataInit.pkIsAnony ?? ''
pkIsAnony: pkDataInit.pkIsAnony ?? '',
userNamePk: pkDataInit.pkUserName ?? ''
});
});
onMounted(() => {
action.value = 'loading';
setTimeout(() => {
queryCompetitionAnswerResult({ execId: pkData.execId }).then(({ body }) => {
const userResult = body.userResult;
pkData.answerResult = body.answerResult; // 答题结果 Y代表我赢,N代表我输
pkData.timeDifference = body.timeDifference; // 时差 int 单位 s
Object.assign(pkData, {
// 自己的
isAnony: userResult.isAnony, // 匿名 String
correctNub: userResult.correctNub, // 正确数 int
qnsNub: userResult.qnsNub, // 总数 int
timeTaken: userResult.timeTaken, // 用时 int
totalScore: userResult.totalScore || 0, // 我方总分
// 对方的
userIdPk: userResult.userIdPk, // 用户Id String
userNamePk: userResult.userNamePk, // 用户姓名 String
imgPk: userResult.imgPk, // 用户姓名 String
pkIsAnony: userResult.isAnonyPk, // 匿名 String
correctNubPk: userResult.correctNubPk, // 正确数 int
qnsNubPk: userResult.qnsNubPk || 0, // 总数 int
timeTakenPk: userResult.timeTakenPk || 0, // 用时 int
totalScorePk: userResult.totalScorePk || 0 // 方总分
});
nextTick(() => {
action.value = 'result';
});
if(mode.value === 'pk_in') {
console.log('调用它');
pointAndBadgesRun('11')
}
// 计算需要额外延时的时间
const currentTime = Math.floor(Date.now() / 1000);
// 2. 计算对手的答题结束时间(秒)
const opponentEndTime = body.endTime + body.timeDifference;
// 3. 计算当前时间到对手结束时间的延迟时间(秒),负数则取0
const delayTime = Math.max(0, opponentEndTime - currentTime);
console.log('计算需要额外延时的时间', delayTime);
setTimeout(() => {
const userResult = body.userResult;
pkData.answerResult = body.answerResult; // 答题结果 Y代表我赢,N代表我输
pkData.timeDifference = body.timeDifference; // 时差 int 单位 s
Object.assign(pkData, {
// 自己的
isAnony: userResult.isAnony, // 名 String
userName: userResult.userName, // 匿名 String
correctNub: userResult.correctNub, // 正确数 int
qnsNub: userResult.qnsNub, // 总数 int
timeTaken: userResult.timeTaken, // 用时 int
totalScore: userResult.totalScore || 0, // 方总分
// 对方的
userIdPk: userResult.userIdPk, // 用户Id String
userNamePk: userResult.userNamePk, // 用户姓名 String
imgPk: userResult.imgPk, // 用户姓名 String
pkIsAnony: userResult.isAnonyPk, // 匿名 String
correctNubPk: userResult.correctNubPk, // 正确数 int
qnsNubPk: userResult.qnsNubPk || 0, // 总数 int
timeTakenPk: userResult.timeTakenPk || 0, // 用时 int
totalScorePk: userResult.totalScorePk || 0 // 对方总分
});
nextTick(() => {
action.value = 'result';
});
if (mode.value === 'pk_in') {
console.log('调用它');
pointAndBadgesRun('11');
}
}, delayTime);
});
}, 2000);
});
@@ -326,6 +326,17 @@
color: #000000;
font-style: normal;
border-bottom: 2rpx solid #efefef;
}
.title_back_icon{
position: absolute;
right: 20rpx;
top: 20rpx;
padding: 10rpx;
.img{
width: 34rpx;
height: 34rpx;
}
}
.note_div {
padding: 20rpx 0 80rpx 0;
+2 -1
View File
@@ -11,6 +11,7 @@
<!-- 3. 最后显示默认标题 -->
<template v-else>{{ title }}</template>
</view>
<view v-if="msg">{{ msg }}</view>
<view class="button_div">
<view class="button_item" v-for="item in buttonList" :style="item?.style" @click="click_button(item)">
{{ item?.name || '' }}
@@ -95,9 +96,9 @@
font-family: PingFangSC;
text-align: center;
font-style: normal;
font-weight: 400;
font-size: 30rpx;
color: #333333;
font-weight: 600;
}
.button_div {
+93 -45
View File
@@ -1,9 +1,9 @@
<template>
<z-paging
ref="pagingRef"
v-model="data_list"
@query="queryList"
class="scroll_div"
:loading-more-enabled="false"
empty-view-text="暂无积分记录"
paging-class="z-paging-class"
>
@@ -14,13 +14,32 @@
<view class="back_div" @click="common.navigateBack()">
<view class="back-icon"></view>
</view>
<view>{{data.actName}}</view>
<view class="title">{{ data.actName }}</view>
</view>
<view class="fl1"></view>
</view>
</view>
</template>
<view class="scroll-Y"></view>
<view class="main-text">
<view class="main-title">活动介绍</view>
{{ data.actEvent }}
<view class="main-title">物品图片</view>
<view class="main-picture">
<image-preview class="img" :src="data.ossAddr" mode="heightFix" :previewDetail="true"></image-preview>
<!-- <image src="" alt="" mode="heightFix"/> -->
</view>
<template v-if="data.itemTyp === '1'">
<view class="main-title">填写地址</view>
<view class="main-area">
<uv-textarea
:disabled="data.actStatus === 'N'"
v-model="data.recAddr"
placeholder="请输入收货地址"
maxlength="100"
></uv-textarea>
</view>
</template>
</view>
<template #bottom>
<uv-button
@click="buttonClick"
@@ -29,6 +48,7 @@
color="#0066FF"
:throttleTime="100"
:text="buttonText"
:disabled="data.actStatus === 'N'"
:loading="buttonLoading"
loadingText="正在兑换中"
:custom-style="customStyle"
@@ -48,65 +68,89 @@
borderRadius: '12rpx'
};
const buttonText = computed(() => {
if(data.actStatus === 'Y') {
return data.excPoints + "积分兑换"
} else if(data.actStatus === 'N') {
return data.actStatusText || '正在获取'
if (data.actStatus === 'Y') {
return data.excPoints + '积分兑换';
} else if (data.actStatus === 'N') {
return data.actStatusText || '正在获取';
}
})
const buttonLoading = ref(false)
});
const pagingRef = ref(null);
const buttonLoading = ref(false);
const data = reactive({
actId:'', // ID
actName:'', // 活动名称
ossAddr:'', // 图片
excPoints:0, // 兑换所需积分
actEvent:'', // 活动介绍
remainingCnt:'', // 剩余数量,库存
itemTyp:'', // 物品类型 0 虚拟 1实体
actStatus:'N', // 是否可以兑换 Y 可以 N不能
actStatusText:'', // 不可以兑换提示的内容
actId: '', // ID
actName: '', // 活动名称
ossAddr: '', // 图片
excPoints: 0, // 兑换所需积分
actEvent: '', // 活动介绍
remainingCnt: '', // 剩余数量,库存
itemTyp: '', // 物品类型 0 虚拟 1实体
actStatus: 'N', // 是否可以兑换 Y 可以 N不能
actStatusText: '', // 不可以兑换提示的内容
recAddr: '' // 兑换的地址
});
const fetchFunction = (params) => {
const queryList = () => {
queryPointsActivityDetail({
actId:data.actId
actId: data.actId
}).then(({ body }) => {
data.actName = body.actName
data.ossAddr = body.ossAddr
data.excPoints = body.excPoints
data.actEvent = body.actEvent
data.remainingCnt = body.remainingCnt
data.itemTyp = body.itemTyp
data.actStatus = body.actStatus
data.actStatusText = body.actStatusText
data.actName = body.actName;
data.ossAddr = body.ossAddr;
data.excPoints = body.excPoints;
data.actEvent = body.actEvent;
data.remainingCnt = body.remainingCnt;
data.itemTyp = body.itemTyp;
data.actStatus = body.actStatus;
data.actStatusText = body.actStatusText;
data.recAddr = body.recAddr;
pagingRef.value.completeByNoMore([1], true);
});
};
const { pagingRef, queryList, data_list } = useZpaging({
fetchFunction
});
const buttonClick = () => {
buttonLoading.value = true
if (data.recAddr === '' && data.itemTyp === '1') return common.msg('地址不能为空');
buttonLoading.value = true;
addPointsExchange({
actId:data.actId,
recAddr:data.recAddr??'地址',
changeValue:data.excPoints,
}).then(({ body }) => {
data.actStatus = body.actStatus
data.actStatusText = body.actStatusText
common.msg(body.result)
}).finally(() => {
buttonLoading.value =false
actId: data.actId,
recAddr: data.recAddr,
changeValue: data.excPoints
})
.then(({ body }) => {
data.actStatus = body.actStatus;
data.actStatusText = body.actStatusText;
common.msg(body.result);
})
.finally(() => {
buttonLoading.value = false;
});
};
onLoad((e) => {
data.actId = e.actId ?? 'TRAPOINTSACTIVITY02501812207220251113142216000003456'
data.actId = e.actId ?? 'TRAPOINTSACTIVITY02501812207220251120133928000019482';
});
onUnload(() => {});
</script>
<style lang="scss" scoped>
#textarea {
background-color: red;
}
.main-text {
padding: 10rpx 30rpx 40rpx 30rpx;
.main-title {
font-size: 30rpx;
font-weight: bold;
margin: 30rpx 0 30rpx 0;
}
.main-picture {
display: flex;
.img {
// width: 300rpx;
height: 360rpx;
// background-color: red;
border-radius: 10rpx;
overflow: hidden;
}
}
}
.send_evaluate {
padding: 28rpx 42rpx 38rpx 42rpx;
}
@@ -166,6 +210,10 @@
position: relative;
text-align: center;
margin-top: var(--status-bar-height);
.title {
max-width: 70%;
margin: 0 auto;
}
.delete_div {
position: absolute;
right: 20rpx;