This commit is contained in:
那些花儿
2025-04-30 14:49:17 +08:00
parent 217e6fc628
commit 459cc348bb
6 changed files with 173 additions and 164 deletions
@@ -25,7 +25,10 @@ import org.nutz.mvc.annotation.Ok;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/** /**
* @author zhf * @author zhf
@@ -49,28 +52,6 @@ public class ActScoreEnterController {
public void index() { public void index() {
} }
@At()
@SaCheckPermission("activity.scoreEnter")
public Result getActivityOptions(Integer year) {
return Result.success(activityService.dao().query(Activity.class, Cnd.NEW().andEX("YEAR(startTime)", "=", year)));
}
@At()
@SaCheckPermission("activity.scoreEnter")
public Result pageData(ActScoreEnterPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
t1.*
FROM
`activity_item` t1
WHERE t1.activityId=@id
ORDER BY t1.sort asc
""").setParam("id", pageForm.getActivityId());
return Result.success(activityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
}
@At("/list-activity") @At("/list-activity")
@SaCheckPermission("activity.scoreEnter") @SaCheckPermission("activity.scoreEnter")
@ApiOperation(value = "获取活动列表", nickname = "/list-activity", httpMethod = "GET") @ApiOperation(value = "获取活动列表", nickname = "/list-activity", httpMethod = "GET")
@@ -91,7 +72,6 @@ public class ActScoreEnterController {
public Result listGroup(Long activityId) { public Result listGroup(Long activityId) {
List<ActGroup> groupList = activityService.dao().query(ActGroup.class, Cnd.where(ActGroup::getActivityId, "=", activityId)); List<ActGroup> groupList = activityService.dao().query(ActGroup.class, Cnd.where(ActGroup::getActivityId, "=", activityId));
return Result.success(groupList); return Result.success(groupList);
} }
/** /**
@@ -110,7 +90,7 @@ public class ActScoreEnterController {
@At("/list-item-score/?") @At("/list-item-score/?")
@SaCheckPermission("activity.scoreEnter") @SaCheckPermission("activity.scoreEnter")
@ApiOperation(value = "获取项目列表", nickname = "/list-item-score", httpMethod = "GET") @ApiOperation(value = "获取队伍项目成绩", nickname = "/list-item-score", httpMethod = "GET")
public Result listItemScore(Long activityId) { public Result listItemScore(Long activityId) {
List<ActItemGroupScore> scoreList = dao.query(ActItemGroupScore.class, Cnd.where(ActItemGroupScore::getActivityId, "=", activityId)); List<ActItemGroupScore> scoreList = dao.query(ActItemGroupScore.class, Cnd.where(ActItemGroupScore::getActivityId, "=", activityId));
return Result.success(scoreList); return Result.success(scoreList);
@@ -119,7 +99,7 @@ public class ActScoreEnterController {
@At("/save-score") @At("/save-score")
@SaCheckPermission("activity.scoreEnter") @SaCheckPermission("activity.scoreEnter")
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@ApiOperation(value = "保存成绩", nickname = "/list-activity", httpMethod = "POST") @ApiOperation(value = "保存成绩", nickname = "/save-score", httpMethod = "POST")
public Result saveScore(ActItemScoreVo actItemScoreVo) { public Result saveScore(ActItemScoreVo actItemScoreVo) {
List<ActivityItem> itemList = dao.query(ActivityItem.class, Cnd.where(ActivityItem::getActivityId, "=", actItemScoreVo.getActivityId())); List<ActivityItem> itemList = dao.query(ActivityItem.class, Cnd.where(ActivityItem::getActivityId, "=", actItemScoreVo.getActivityId()));
// dao.clear(ActItemGroupScore.class, Cnd.where(ActItemGroupScore::getActivityId, "=", actItemScoreVo.getActivityId())); // dao.clear(ActItemGroupScore.class, Cnd.where(ActItemGroupScore::getActivityId, "=", actItemScoreVo.getActivityId()));
@@ -144,8 +124,17 @@ public class ActScoreEnterController {
activityItemScores.add(score); activityItemScores.add(score);
}); });
}); });
dao.update(activityItemScores); dao.update(activityItemScores);
// 更新队伍得分及排名
List<ActGroup> groups = dao.query(ActGroup.class, Cnd.where(ActGroup::getActivityId, "=", actItemScoreVo.getActivityId()));
for (ActGroup group : groups) {
List<ActItemGroupScore> groupScores = activityItemScores.stream().filter(item -> item.getGroupId().equals(group.getId())).collect(Collectors.toList());
groupScores.stream().map(v -> v.getScore()).reduce(BigDecimal::add).ifPresent(group::setTotalScore);
}
groups.sort(Comparator.comparing(ActGroup::getTotalScore).reversed());
IntStream.range(0, groups.size()).forEach(i -> groups.get(i).setTotalRank(i + 1));
dao.update(groups, "totalScore|totalRank");
return Result.success(); return Result.success();
} }
@@ -182,20 +182,19 @@ layout("/layouts/platform_1.html"){
cellClick(row, column) { cellClick(row, column) {
}, },
// 保存成绩 // 保存成绩
saveScore() { async saveScore() {
const formData = { const formData = {
activityId: this.pageForm.activityId, activityId: this.pageForm.activityId,
data: JSON.stringify(this.tableData) data: JSON.stringify(this.tableData)
} }
$.post("/platform/activity/scoreEnter/save-score", formData).then(async res => { const {code,data,msg} = await $.post("/platform/activity/scoreEnter/save-score", formData)
if (res.code === 0) { if (code === 0) {
await this.listItemScore() await this.listItemScore()
this.buildTableData() this.buildTableData()
this.$message.success("保存成功") this.$message.success("保存成功")
} else { }else{
this.$message.error(res.msg) this.$message.error(msg)
} }
})
console.log(this.tableData) console.log(this.tableData)
} }
}, },
+102 -83
View File
@@ -1,96 +1,108 @@
<template> <template>
<view class="page-container"> <view class="page-container">
<t-dropdown-menu class="top-dropdown"> <template v-if="actOptions && actOptions.length > 0">
<t-dropdown-item :options="actOptions" :value="selectActId" @change="getSignInfo"/> <t-dropdown-menu class="top-dropdown">
</t-dropdown-menu> <t-dropdown-item :options="actOptions" :value="selectActId" @change="getSignInfo"/>
<view class="content-container"> </t-dropdown-menu>
<view class="scan-area animate__animated animate__fadeIn" @click="handleScan"> <view class="content-container">
<view class="scan-icon-wrapper pulse-animation"> <view class="scan-area animate__animated animate__fadeIn" @click="handleScan">
<t-icon name="scan" size="80" color="#f45a5a"></t-icon> <view class="scan-icon-wrapper pulse-animation">
<view class="scan-circles"></view> <t-icon name="scan" size="80" color="#f45a5a"></t-icon>
<view class="scan-circles"></view>
</view>
<t-button shape="round"
theme="primary"
size="medium"
class="scan-button">扫描二维码签到
</t-button>
</view> </view>
<t-button shape="round" <view class="guide-area animate__animated animate__fadeInUp">
theme="primary" <view class="guide-title">签到说明</view>
size="medium" <view class="guide-list">
class="scan-button">扫描二维码签到 <view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.1s">
</t-button> <t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon>
</view> <text class="guide-text">请对准活动二维码进行扫描</text>
<view class="guide-area animate__animated animate__fadeInUp"> </view>
<view class="guide-title">签到说明</view> <view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.2s">
<view class="guide-list"> <t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon>
<view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.1s"> <text class="guide-text">确保手机相机权限已开启</text>
<t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon> </view>
<text class="guide-text">请对准活动二维码进行扫描</text> <view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.3s">
</view> <t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon>
<view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.2s"> <text class="guide-text">保持二维码清晰可见</text>
<t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon> </view>
<text class="guide-text">确保手机相机权限已开启</text>
</view>
<view class="guide-item animate__animated animate__fadeInLeft" style="animation-delay: 0.3s">
<t-icon name="notification" size="16" color="#ff5f5c" class="guide-icon"></t-icon>
<text class="guide-text">保持二维码清晰可见</text>
</view> </view>
</view> </view>
</view> <view class="current-status-area animate__animated animate__fadeInUp" style="animation-delay: 0.2s">
<view class="current-status-area animate__animated animate__fadeInUp" style="animation-delay: 0.2s"> <view class="status-header">
<view class="status-header"> <text class="status-title">当前签到状态</text>
<text class="status-title">当前签到状态</text> </view>
</view> <view v-if="signInfo" class="status-content">
<view v-if="signInfo" class="status-content"> <template v-if="signInfo.isSignIn">
<template v-if="signInfo.isSignIn"> <view class="sign-success">
<view class="sign-success"> <div class="success-icon-wrapper">
<div class="success-icon-wrapper"> <t-icon name="task-checked-1" size="48" color="#07c160"></t-icon>
<t-icon name="task-checked-1" size="48" color="#07c160"></t-icon> <svg class="checkmark-circle" viewBox="0 0 52 52">
<svg class="checkmark-circle" viewBox="0 0 52 52"> <circle class="checkmark-circle__circle" cx="26" cy="26" r="25" fill="none" />
<circle class="checkmark-circle__circle" cx="26" cy="26" r="25" fill="none" /> </svg>
</svg> </div>
</div> <text class="success-text">已完成签到</text>
<text class="success-text">已完成签到</text> <view class="sign-detail">
<view class="sign-detail"> <view class="detail-item">
<view class="detail-item"> <uni-icons type="calendar" size="14" color="#666666"/>
<uni-icons type="calendar" size="14" color="#666666"/> <text>签到时间:{{ signInfo.signInTime }}</text>
<text>签到时间:{{ signInfo.signInTime }}</text> </view>
<!-- <view class="detail-item">-->
<!-- <uni-icons type="location" size="14" color="#666666"/>-->
<!-- <text>签到地点:{{ signInfo.location }}</text>-->
<!-- </view>-->
</view> </view>
<!-- <view class="detail-item">-->
<!-- <uni-icons type="location" size="14" color="#666666"/>-->
<!-- <text>签到地点:{{ signInfo.location }}</text>-->
<!-- </view>-->
</view> </view>
</view> </template>
</template> <template v-else>
<template v-else> <view class="sign-pending">
<view class="sign-pending"> <t-icon name="info-circle" size="48" color="#f45a5a"></t-icon>
<t-icon name="info-circle" size="48" color="#f45a5a"></t-icon> <text class="pending-text">待签到</text>
<text class="pending-text">待签到</text> <text class="pending-tip">请使用扫码签到完成签到</text>
<text class="pending-tip">请使用扫码签到完成签到</text> </view>
</view> </template>
</template> </view>
</view> </view>
</view> </view>
</view> <div class="bg-decoration">
<svg class="wave" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<path fill="#f45a5a" fill-opacity="0.1" d="M0,160L48,154.7C96,149,192,139,288,144C384,149,480,171,576,176C672,181,768,171,864,154.7C960,139,1056,117,1152,128C1248,139,1344,181,1392,202.7L1440,224L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path>
</svg>
<svg class="dots" width="100" height="100" viewBox="0 0 100 100">
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="10" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="50" r="3" />
</svg>
</div>
</template>
<div class="bg-decoration"> <view style="flex: 1;display: flex;justify-content: center;align-items: center">
<svg class="wave" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"> <t-empty v-if="actOptions && actOptions.length === 0"
<path fill="#f45a5a" fill-opacity="0.1" d="M0,160L48,154.7C96,149,192,139,288,144C384,149,480,171,576,176C672,181,768,171,864,154.7C960,139,1056,117,1152,128C1248,139,1344,181,1392,202.7L1440,224L1440,0L1392,0C1344,0,1248,0,1152,0C1056,0,960,0,864,0C768,0,672,0,576,0C480,0,384,0,288,0C192,0,96,0,48,0L0,0Z"></path> image="/static/img/empty.png"
</svg> description="报名活动后才能扫码签到"
<svg class="dots" width="100" height="100" viewBox="0 0 100 100"> style="flex: 1">
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="10" r="3" /> <template #action>
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="10" r="3" /> <t-button theme="primary" shape="round" size="large" @click="navigateToSignUp">去报名列表看看</t-button>
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="10" r="3" /> </template>
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="10" r="3" /> </t-empty>
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="10" r="3" /> </view>
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="30" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="10" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="30" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="50" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="70" cy="50" r="3" />
<circle fill="#f45a5a" fill-opacity="0.2" cx="90" cy="50" r="3" />
</svg>
</div>
</view> </view>
<ScanQRCode <ScanQRCode
@@ -205,6 +217,13 @@ async function signIn() {
} }
} }
// 去报名列表
function navigateToSignUp(){
uni.redirectTo({
url: '/pages/activity/list/index'
})
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
+39 -32
View File
@@ -1,43 +1,50 @@
<template> <template>
<view class="page-container"> <view class="page-container">
<t-dropdown-menu class="top-dropdown"> <template v-if="actOptions && actOptions.length>0">
<t-dropdown-item :options="actOptions" :value="selectActId"/> <t-dropdown-menu class="top-dropdown">
</t-dropdown-menu> <t-dropdown-item :options="actOptions" :value="selectActId"/>
</t-dropdown-menu>
<view class="content-container">
<view class="page-header">
<text class="page-title">团队报名</text>
<text class="page-subtitle">点击项目报名</text>
</view>
<view class="content-container"> <!-- 项目列表 -->
<view class="page-header"> <view class="project-cards">
<text class="page-title">团队报名</text> <view
<text class="page-subtitle">点击项目报名</text> v-for="project in itemOptions"
</view> :key="project.id"
class="project-card"
<!-- 项目列表 --> :class="{'project-card--registered': registrationStatus.get(project.id)?.length}"
<view class="project-cards"> @click="selectProject(project.id)"
<view >
v-for="project in itemOptions" <view class="project-card__content">
:key="project.id" <view class="project-card__title">{{ project.name }}</view>
class="project-card" <view class="project-card__desc">{{ project.description }}</view>
:class="{'project-card--registered': registrationStatus.get(project.id)?.length}"
@click="selectProject(project.id)"
>
<view class="project-card__content">
<view class="project-card__title">{{ project.name }}</view>
<view class="project-card__desc">{{ project.description }}</view>
</view>
<view class="project-card__status">
<t-tag v-if="registrationStatus.get(project.id)?.length" theme="success" variant="light-outline">
已报名 {{ registrationStatus.get(project.id)?.length }}人
</t-tag>
<view v-else class="project-card__action">
<t-icon name="chevron-right" color="#999"/>
</view> </view>
<view class="project-card__status">
<t-tag v-if="registrationStatus.get(project.id)?.length" theme="success" variant="light-outline">
已报名 {{ registrationStatus.get(project.id)?.length }}人
</t-tag>
<view v-else class="project-card__action">
<t-icon name="chevron-right" color="#999"/>
</view>
</view>
<!-- <view v-if="registrationStatus.get(project.id)?.length" class="project-card__checkmark">
<t-icon name="check" color="#52c41a"/>
</view>-->
</view> </view>
<!-- <view v-if="registrationStatus.get(project.id)?.length" class="project-card__checkmark">
<t-icon name="check" color="#52c41a"/>
</view>-->
</view> </view>
</view> </view>
</template>
<view v-else style="flex: 1;display: flex;justify-content: center;align-items: center">
<t-empty v-if="actOptions && actOptions.length === 0"
image="/static/img/empty.png"
description="您没有任何团队信息,无法进行项目报名"
style="flex: 1">
</t-empty>
</view> </view>
<t-popup v-model:visible="showMemberPicker" placement="bottom" destroy-on-close> <t-popup v-model:visible="showMemberPicker" placement="bottom" destroy-on-close>
<view class="member-picker"> <view class="member-picker">
<view class="picker-header"> <view class="picker-header">
+8 -13
View File
@@ -42,7 +42,8 @@
<!-- 项目报名按钮 --> <!-- 项目报名按钮 -->
<div class="action-section"> <div class="action-section">
<t-button block theme="danger" size="large" class="register-btn" @click="goToEventRegistration" :disabled="!team.teamIsLeader"> <t-button block theme="danger" size="large" class="register-btn" @click="goToEventRegistration"
:disabled="!team.teamIsLeader">
<div v-if="team.teamIsLeader"> {{ team.isSelfLeader ? '参与项目报名' : '查看项目报名' }}</div> <div v-if="team.teamIsLeader"> {{ team.isSelfLeader ? '参与项目报名' : '查看项目报名' }}</div>
<div v-else>暂无队长无法报名</div> <div v-else>暂无队长无法报名</div>
</t-button> </t-button>
@@ -115,18 +116,12 @@
</div> </div>
</div> </div>
</view> </view>
<view v-else style="background-color: #FFFFFF"> <view v-else style="flex: 1;display: flex;justify-content: center;align-items: center">
<view> <t-empty v-if="actOptions && actOptions.length === 0"
<t-result> image="/static/img/empty.png"
<template #image> description="您没有任何团队信息"
<t-image src="https://tdesign.gtimg.com/mobile/demos/result1.png" class="external-class-image"/> style="flex: 1">
</template> </t-empty>
<template #title>
<div>暂无团队</div>
</template>
</t-result>
</view>
</view> </view>
</view> </view>
<t-dialog <t-dialog
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB