diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientGroupController.java b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientGroupController.java index d74a123..cea7cd9 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientGroupController.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientGroupController.java @@ -4,15 +4,21 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import com.budwk.app.base.result.Result; import com.budwk.app.client.module.activity.service.ClientActivityService; import com.budwk.app.module.activity.models.ActGroup; +import com.budwk.app.module.activity.models.ActGroupUser; import com.budwk.app.module.activity.models.ActUser; +import com.budwk.app.module.activity.models.ActivityItem; import com.budwk.app.web.commons.auth.satoken.StpClientUtil; +import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; +import org.nutz.mvc.adaptor.JsonAdaptor; +import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -37,11 +43,12 @@ public class ClientGroupController { /** * 查询我的活动 + * * @return */ @At("/list-act") @SaCheckLogin(type = StpClientUtil.TYPE) - public Result listAct(){ + public Result listAct() { Sql sql = Sqls.create(""" SELECT t1.id, @@ -64,19 +71,60 @@ public class ClientGroupController { @At("/info/?") @SaCheckLogin(type = StpClientUtil.TYPE) - public Result info(Long activityId){ - ActGroup group = dao.fetch(ActGroup.class, Cnd.where(ActGroup::getActivityId, "=", activityId)); + public Result info(Long activityId) { + Sql sql = Sqls.create("select * from act_group where activityId=@activityId").setParam("activityId", activityId); + sql.setCallback(Sqls.callback.map()); + NutMap map = (NutMap) dao.execute(sql).getResult(); + Sql sqlGroupUser = Sqls.create(""" + SELECT + t1.*, + t2.userName, + t2.unitName, + t2.sex + FROM + `act_group_user` t1 + LEFT JOIN act_user t2 ON t1.userId = t2.userId + WHERE t1.groupId=@groupId + """).setParam("groupId", map.getString("id")); + List groupUsers = clientActivityService.listMap(sqlGroupUser); + map.put("groupUsers", groupUsers); + NutMap leader = groupUsers.stream().filter(nutMap -> nutMap.getBoolean("isLeader")).findFirst().orElse(null); + map.put("isSelfLeader", ""); + if (Lang.isNotEmpty(leader)) { + map.put("isSelfLeader", leader.getString("userId").equals(StpClientUtil.STP.getLoginIdAsString())); + } + + return Result.success(map); + } + + + @At("/apply-leader/?") + @AdaptBy(type = JsonAdaptor.class) + @SaCheckLogin(type = StpClientUtil.TYPE) + public Result applyLeader(Long groupId) { + clientActivityService.dao().update(ActGroupUser.class, + Chain.make("isLeader", true), + Cnd.where(ActGroupUser::getGroupId, "=", groupId) + .and(ActGroupUser::getUserId, "=", StpClientUtil.STP.getLoginIdAsLong())); return Result.success(); } - - /** - * 查询团队成员 - */ - @At("/list-team-user/?") + @At("/list-team/?") @SaCheckLogin(type = StpClientUtil.TYPE) - public Result listTeamUser(Long activityId){ - List list = dao.query(ActUser.class, Cnd.where(ActUser::getActivityId, "=", activityId).and(ActUser::getIsSignIn, "=", 1)); + public Result listTeam(Long activityId){ + Sql sql = Sqls.create(""" + SELECT + t1.*, + COUNT( t2.id ) isSignUp + FROM + activity_item t1 + LEFT JOIN act_item_user t2 ON t1.id = t2.itemId + WHERE + t1.activityId = @activityId + GROUP BY + t1.id + """).setParam("activityId",activityId); + List list = clientActivityService.listMap(sql); return Result.success(list); } } diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientItemController.java b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientItemController.java index 855a93c..dbc5dd4 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientItemController.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/controller/ClientItemController.java @@ -5,14 +5,18 @@ import com.budwk.app.base.result.Result; import com.budwk.app.client.module.activity.service.ClientItemService; import com.budwk.app.client.module.activity.vo.ClientActivitySignVO; import com.budwk.app.client.module.activity.vo.ClientItemSignUpVO; +import com.budwk.app.module.activity.models.ActGroup; import com.budwk.app.module.activity.models.ActUser; import com.budwk.app.module.activity.models.ActivityItem; import com.budwk.app.module.activity.models.ActivityItemUser; import com.budwk.app.web.commons.auth.satoken.StpClientUtil; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; import org.nutz.mvc.adaptor.JsonAdaptor; import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; @@ -41,6 +45,19 @@ public class ClientItemController { return Result.success(); } + + /** + * 查询出这个活动所有报名的人 + * @param activityId + * @return + */ + @At("/list-apply-user/?") + @SaCheckLogin(type = StpClientUtil.TYPE) + public Result listApplyUser(String activityId){ + List userList = dao.query(ActivityItemUser.class, Cnd.where(ActivityItemUser::getActivityId, "=", activityId)); + return Result.success(userList); + } + /** * 获取项目列表 */ @@ -56,8 +73,23 @@ public class ClientItemController { */ @At("/list-team-user/?") @SaCheckLogin(type = StpClientUtil.TYPE) - public Result listTeamUser(Long activityId){ - List list = dao.query(ActUser.class, Cnd.where(ActUser::getActivityId, "=", activityId).and(ActUser::getIsSignIn, "=", 1)); + public Result listTeamUser(Long activityId) { + Sql sql = Sqls.create(""" + SELECT + t1.groupId, + t1.userId, + t2.activityId, + t3.userName, + t3.unitName, + t3.sex + FROM + `act_group_user` t1 + LEFT JOIN act_group t2 ON t2.id = t1.groupId + LEFT JOIN act_user t3 ON t3.userId = t1.userId + WHERE + t2.activityId = @activityId + """).setParam("activityId", activityId); + List list = clientItemService.listMap(sql); return Result.success(list); } @@ -66,7 +98,7 @@ public class ClientItemController { */ @At("/list-signup-user") @SaCheckLogin - public Result listSignUpUser(Long activityId,Long itemId) { + public Result listSignUpUser(Long activityId, Long itemId) { List itemUsers = dao.query(ActivityItemUser.class, Cnd.where(ActivityItemUser::getActivityId, "=", activityId).and(ActivityItemUser::getItemId, "=", itemId)); return Result.success(itemUsers); } diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/service/impl/ClientItemServiceImpl.java b/backend/src/main/java/com/budwk/app/client/module/activity/service/impl/ClientItemServiceImpl.java index 7201e99..515808c 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/service/impl/ClientItemServiceImpl.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/service/impl/ClientItemServiceImpl.java @@ -3,6 +3,7 @@ package com.budwk.app.client.module.activity.service.impl; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.client.module.activity.service.ClientItemService; import com.budwk.app.client.module.activity.vo.ClientItemSignUpVO; +import com.budwk.app.module.activity.models.Activity; import com.budwk.app.module.activity.models.ActivityItemUser; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; @@ -10,6 +11,8 @@ import org.nutz.dao.Dao; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.IocBean; +import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; @IocBean(args = {"refer:dao"}) @@ -21,17 +24,24 @@ public class ClientItemServiceImpl extends BaseServiceImpl imp @Override @Aop(TransAop.READ_COMMITTED) public void signUp(ClientItemSignUpVO signVO) { + Activity activity = dao().fetch(Activity.class, Cnd.where(Activity::getId, "=", signVO.getActivityId())); + if (activity.getItemEndTime().isBefore(LocalDateTime.now())){ + throw new RuntimeException("项目报名已结束!"); + } // 删除掉之前的 clear(Cnd.where(ActivityItemUser::getActivityId, "=", signVO.getActivityId()) .and(ActivityItemUser::getGroupId, "=", signVO.getGroupId()) .and(ActivityItemUser::getItemId, "=", signVO.getItemId()) ); - List userList = signVO.getUserList(); - for (ActivityItemUser itemUser : userList) { + List userList = new ArrayList<>(); + for (Long userId : signVO.getUserList()) { + ActivityItemUser itemUser = new ActivityItemUser(); itemUser.setActivityId(signVO.getActivityId()); itemUser.setItemId(signVO.getItemId()); itemUser.setGroupId(signVO.getGroupId()); + itemUser.setUserId(userId); + userList.add(itemUser); } insert(userList); } diff --git a/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientItemSignUpVO.java b/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientItemSignUpVO.java index 0392944..711d5b0 100644 --- a/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientItemSignUpVO.java +++ b/backend/src/main/java/com/budwk/app/client/module/activity/vo/ClientItemSignUpVO.java @@ -14,6 +14,6 @@ public class ClientItemSignUpVO { private Long groupId; - private List userList; + private List userList; } diff --git a/backend/src/main/java/com/budwk/app/module/activity/controller/ActScoreEnterController.java b/backend/src/main/java/com/budwk/app/module/activity/controller/ActScoreEnterController.java new file mode 100644 index 0000000..22d4012 --- /dev/null +++ b/backend/src/main/java/com/budwk/app/module/activity/controller/ActScoreEnterController.java @@ -0,0 +1,81 @@ +package com.budwk.app.module.activity.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.module.activity.models.ActGroup; +import com.budwk.app.module.activity.models.Activity; +import com.budwk.app.module.activity.service.ActivityManageService; +import com.budwk.app.module.activity.vo.page.ActScoreEnterPageForm; +import com.budwk.app.module.activity.vo.page.ActSignInUserPageForm; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @author zhf + * @date 2025/4/29 15:56 + * @description 成绩录入 + */ +@IocBean +@At("/platform/activity/scoreEnter") +@Ok("json:full") +public class ActScoreEnterController { + + + @Inject + private Dao dao; + @Inject + private ActivityManageService activityService; + + @At("") + @SaCheckPermission("activity.scoreEnter") + @Ok("beetl:/platform/activity/scoreEnter/index.html") + 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)); + } + + + /** + * 获取分组列表 + * @param activityId + * @return + */ + @At() + @SaCheckPermission("activity.scoreEnter") + public Result getGroupList(Long activityId){ + List groupList = activityService.dao().query(ActGroup.class, Cnd.where(ActGroup::getActivityId, "=", activityId)); + return Result.success(groupList); + + } + + +} diff --git a/backend/src/main/java/com/budwk/app/module/activity/models/Activity.java b/backend/src/main/java/com/budwk/app/module/activity/models/Activity.java index cb6c2a9..1e79c50 100644 --- a/backend/src/main/java/com/budwk/app/module/activity/models/Activity.java +++ b/backend/src/main/java/com/budwk/app/module/activity/models/Activity.java @@ -50,6 +50,16 @@ public class Activity extends BaseModel { @ColDefine(type = ColType.DATETIME) private LocalDateTime signEndTime; + @Comment("项目报名开始时间") + @Column + @ColDefine(type = ColType.DATETIME) + private LocalDateTime itemStartTime; + + @Comment("项目报名结束时间") + @Column + @ColDefine(type = ColType.DATETIME) + private LocalDateTime itemEndTime; + @Comment("主办单位") @Column @ColDefine(type = ColType.VARCHAR, width = 255) diff --git a/backend/src/main/java/com/budwk/app/module/activity/models/ActivityItemScore.java b/backend/src/main/java/com/budwk/app/module/activity/models/ActivityItemScore.java new file mode 100644 index 0000000..2d08135 --- /dev/null +++ b/backend/src/main/java/com/budwk/app/module/activity/models/ActivityItemScore.java @@ -0,0 +1,30 @@ +package com.budwk.app.module.activity.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; + +/** + * @author zhf + * @date 2025/4/29 16:41 + * @description 活动成绩 + */ +@EqualsAndHashCode(callSuper = true) +@Table("activity_item") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("活动成绩") +@Data +public class ActivityItemScore extends BaseModel { + + @Id + @Comment("ID") + private Long id; + + @Column + @Comment("活动ID") + @ColDefine(type = ColType.INT) + private Long activityId; + + +} diff --git a/backend/src/main/java/com/budwk/app/module/activity/vo/page/ActScoreEnterPageForm.java b/backend/src/main/java/com/budwk/app/module/activity/vo/page/ActScoreEnterPageForm.java new file mode 100644 index 0000000..9058433 --- /dev/null +++ b/backend/src/main/java/com/budwk/app/module/activity/vo/page/ActScoreEnterPageForm.java @@ -0,0 +1,19 @@ +package com.budwk.app.module.activity.vo.page; + +import com.budwk.app.base.page.PageForm; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author zhf + * @date 2025/4/29 16:08 + * @description + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ActScoreEnterPageForm extends PageForm { + + // 活动ID + private Long activityId; + +} diff --git a/backend/src/main/resources/views/platform/activity/manage/addOrUpdate.js b/backend/src/main/resources/views/platform/activity/manage/addOrUpdate.js index eb03b96..5e27579 100644 --- a/backend/src/main/resources/views/platform/activity/manage/addOrUpdate.js +++ b/backend/src/main/resources/views/platform/activity/manage/addOrUpdate.js @@ -6,7 +6,7 @@ const addOrUpdate = { - + @@ -43,6 +43,22 @@ const addOrUpdate = { + + + + + + + + + + + + @@ -95,6 +111,12 @@ const addOrUpdate = { signEndTime: [ {required: true, message: '请选择报名结束时间', trigger: ['blur', 'change']} ], + itemStartTime: [ + {required: true, message: '请选择项目报名开始时间', trigger: ['blur', 'change']} + ], + itemEndTime: [ + {required: true, message: '请选择项目报名结束时间', trigger: ['blur', 'change']} + ], hostUnit: [{required: true, message: '请输入主办单位', trigger: ['blur', 'change']}], coHostUnit: [{required: true, message: '请输入承办单位', trigger: ['blur', 'change']}], contact: [{required: true, message: '请输入联系人', trigger: ['blur', 'change']}], diff --git a/backend/src/main/resources/views/platform/activity/scoreEnter/addOrUpdate.js b/backend/src/main/resources/views/platform/activity/scoreEnter/addOrUpdate.js new file mode 100644 index 0000000..4ac8e15 --- /dev/null +++ b/backend/src/main/resources/views/platform/activity/scoreEnter/addOrUpdate.js @@ -0,0 +1,79 @@ +const addOrUpdate = { + template: /*language=HTML*/ ` + + + + + + + + + + + + + + + + + + + + + `, + data() { + return { + title: '', + visible: false, + infoData: {}, + tableData: [], + groupList: [] + } + }, + methods: { + onOpen(row) { + this.infoData = row + this.getGroupList() + this.visible = true + + }, + getGroupList() { + $.get('/platform/activity/scoreEnter/getGroupList', {activityId: this.infoData.activityId}).then(res => { + if (res.code === 0) { + this.groupList = res.data + } + }) + }, + onSubmit() { + $.post('/platform/activity/scoreEnter/addOrUpdate', { + activityId: this.infoData.activityId, + itemId: this.infoData.id, + scores: JSON.stringify(this.tableData) + }).then(res => { + if (res.code === 0) { + this.$message.success('保存成功') + this.visible = false + } else { + this.$message.error(res.msg) + } + }) + + } + } + +} diff --git a/backend/src/main/resources/views/platform/activity/scoreEnter/index.html b/backend/src/main/resources/views/platform/activity/scoreEnter/index.html new file mode 100644 index 0000000..926ea85 --- /dev/null +++ b/backend/src/main/resources/views/platform/activity/scoreEnter/index.html @@ -0,0 +1,110 @@ + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/frontend/src/pages/activity/team-form/index.vue b/frontend/src/pages/activity/team-form/index.vue index bf28c77..79340b5 100644 --- a/frontend/src/pages/activity/team-form/index.vue +++ b/frontend/src/pages/activity/team-form/index.vue @@ -16,7 +16,7 @@ v-for="project in itemOptions" :key="project.id" class="project-card" - :class="{'project-card--registered': registrationStatus[project.id]?.length}" + :class="{'project-card--registered': registrationStatus.get(project.id)?.length}" @click="selectProject(project.id)" > @@ -24,14 +24,14 @@ {{ project.description }} - - 已报名 {{ registrationStatus[project.id]?.length }}人 + + 已报名 {{ registrationStatus.get(project.id)?.length }}人 - + @@ -53,24 +53,19 @@ - - 已报名 - - - + 确认报名 ({{ selectedMemberIds.length }}人) @@ -116,14 +111,15 @@ const teamMembers = ref([]); onLoad((option) => { if (option.id) { - selectActId.value = option.id; + selectActId.value = Number(option.id); } }); onMounted(async () => { await listActs() await listItems(); - listTeamUser() - // fetchRegistrationStatus(); + await listTeamUser(); + await getApplyUsers(); + fetchRegistrationStatus(); }); // 选中的团队成员 @@ -132,8 +128,7 @@ const selectedMemberIds = ref([]); // 成员选择弹窗显示状态 const showMemberPicker = ref(false); -// 当前项目的报名状态 -const registrationStatus = ref({}); + // 获取活动列表 async function listActs() { @@ -146,9 +141,9 @@ async function listActs() { label: item.title } }) - if(selectActId.value === null && data.length){ - selectActId.value = data[0].id - } + // if(selectActId.value === null && data.length){ + // selectActId.value = data[0].id + // } } else { Toast.error(msg) } @@ -171,61 +166,80 @@ async function listItems() { } // 获取团队成员 -async function listTeamUser(){ +async function listTeamUser() { try { - const {code, data, msg} = await request.get('/client/item/list-team-user/'+selectActId.value) + const {code, data, msg} = await request.get('/client/item/list-team-user/' + selectActId.value) if (code === 0) { teamMembers.value = data; - }else{ + } else { Toast.error(msg) } - }catch (e){ + } catch (e) { Toast.error(msg) console.error(e) } } +// 当前项目的报名状态 +const registrationStatus = ref(new Map()); // 获取报名状态 - 使用静态数据 -const fetchRegistrationStatus = async () => { +const fetchRegistrationStatus = () => { + const resultMap = selectedMemberList.value.reduce((acc, item) => { + const key = item.itemId; + if (!acc.has(key)) { + acc.set(key, []); + } + acc.get(key).push(item); + return acc; + }, new Map()); + registrationStatus.value = resultMap; }; // 选择项目 const selectProject = (projectId) => { selectedItemId.value = projectId; - selectedMemberIds.value = []; + selectedMemberIds.value = selectedMemberList.value.filter(v => v.itemId === projectId).map(v => v.userId) + showMemberPicker.value = true; }; +const selectedMemberList = ref([]) +// 每个项目报名的user +const getApplyUsers = async () => { + try { + const {code, data, msg} = await useRequest().post('/client/item/list-apply-user/' + selectActId.value) + if (code === 0) { + selectedMemberList.value = data + } else { + Toast.error(msg) + } + } catch (e) { + Toast.error(e.message) + } +} + + // 提交报名 - 使用静态数据模拟 const submitRegistration = async () => { - if (!selectedMemberIds.value.length) { - Toast.warning('请选择团队成员'); - return; - } try { - console.log(selectedMemberIds.value) - console.log(selectedItemId.value) - console.log(selectActId.value) - - const teamUser = teamMembers.value.filter(v=>selectedMemberIds.value.includes(v.id)) - - // const {code, msg} = await request.post('/client/item/sign-up', { - // activityId: selectActId.value, - // itemId: selectedItemId.value, - // userList: selectedMemberIds.value - // }) - // if (code === 0) { - // Toast.success('报名成功') - // showMemberPicker.value = false; - // selectedMemberIds.value = [] - // }else{ - // Toast.error(msg) - // } - }catch (e){ + let data = {} + data.activityId = selectActId.value + data.itemId = selectedItemId.value + data.userList = selectedMemberIds.value + const {code, msg} = await useRequest().post('/client/item/sign-up', {...data}) + if (code === 0) { + Toast.success('报名成功') + showMemberPicker.value = false; + selectedMemberIds.value = [] + await getApplyUsers(); + fetchRegistrationStatus(); + } else { + Toast.error(msg) + } + } catch (e) { Toast.error(e.message) - console.error(e) } }; diff --git a/frontend/src/pages/activity/team/index.vue b/frontend/src/pages/activity/team/index.vue index 9a6a119..9176656 100644 --- a/frontend/src/pages/activity/team/index.vue +++ b/frontend/src/pages/activity/team/index.vue @@ -1,118 +1,109 @@ + +