This commit is contained in:
那些花儿
2025-05-15 14:44:27 +08:00
parent 277ddf9e6a
commit 053edabb58
18 changed files with 548 additions and 216 deletions
@@ -81,7 +81,8 @@ public class ClientGroupController {
ActGroupUser groupUser = dao.fetch(ActGroupUser.class, Cnd.where(ActGroupUser::getUserId, "=", StpClientUtil.STP.getLoginIdAsLong())
.and(ActGroupUser::getActivityId, "=", activityId));
if (Lang.isEmpty(groupUser)) {
return Result.error("您还没加入任何团队");
// return Result.error("您还没加入任何团队");
return Result.success();
}
Sql sql = Sqls.create("select * from act_group where id=@id").setParam("id", groupUser.getGroupId());
sql.setCallback(Sqls.callback.map());
@@ -84,6 +84,11 @@ public class ClientActivityServiceImpl extends BaseServiceImpl<Activity> impleme
user.setSignUpMobile(signVO.getContactPhone());
user.setSignUpUserId(StpClientUtil.STP.getLoginIdAsLong());
user.setSignUpTime(now);
if(!user.getTraffic().equals("自驾")){
user.setCarNo(null);
}
}
// delete then insert so easy
@@ -32,6 +32,7 @@ import org.nutz.mvc.annotation.Param;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;
/**
@@ -265,7 +266,7 @@ public class ActGroupController {
for (ActGroup group : actGroups) {
List<ActItemGroupScore> scores = dao.query(ActItemGroupScore.class, Cnd.where(ActItemGroupScore::getGroupId, "=", group.getId())
.and(ActivityItem::getActivityId, "=", activityId));
BigDecimal total = scores.stream().map(ActItemGroupScore::getScore).reduce(BigDecimal::add).orElse(new BigDecimal(0));
BigDecimal total = scores.stream().map(ActItemGroupScore::getScore).filter(Objects::nonNull).reduce(BigDecimal::add).orElse(new BigDecimal(0));
group.setTotalScore(total);
}
dao.update(actGroups, "totalScore");
@@ -242,9 +242,13 @@ public class ActUserController {
add(new ExcelExportEntity("所属单位", "unitName", 20));
add(new ExcelExportEntity("报名时间", "signUpTime2", 20));
add(new ExcelExportEntity("是否签到", "isSignInDesc", 20));
add(new ExcelExportEntity("是否展示才艺", "isShowSkillDesc", 20));
add(new ExcelExportEntity("才艺名称", "skillName", 20));
add(new ExcelExportEntity("所需器材", "equip", 20));
// add(new ExcelExportEntity("是否展示才艺", "isShowSkillDesc", 20));
// add(new ExcelExportEntity("才艺名称", "skillName", 20));
// add(new ExcelExportEntity("所需器材", "equip", 20));
add(new ExcelExportEntity("交通方式", "traffic", 20));
add(new ExcelExportEntity("自驾车牌号", "carNo", 20));
add(new ExcelExportEntity("是否接站", "isStationDesc", 20));
add(new ExcelExportEntity("是否参加嘉年华", "isPartyDesc", 20));
}};
response.setContentType("application/octet-stream");
@@ -121,10 +121,10 @@ public class ActivitySignInQueryController {
WHEN 1 THEN '已发放'
WHEN 0 THEN '未发放'
END AS isGrantDesc,
CASE au.isShowSkill
CASE au.isStation
WHEN 1 THEN '是'
WHEN 0 THEN ''
END AS isShowSkillDesc,
END AS isStationDesc,
CASE au.isParty
WHEN 1 THEN '是'
WHEN 0 THEN ''
@@ -157,9 +157,12 @@ public class ActivitySignInQueryController {
add(new ExcelExportEntity("签到时间", "signInTime", 20));
add(new ExcelExportEntity("是否住宿", "isStayDesc", 20));
// add(new ExcelExportEntity("物资发放", "isGrantDesc", 20));
add(new ExcelExportEntity("是否展示才艺", "isShowSkillDesc", 20));
add(new ExcelExportEntity("才艺名称", "skillName", 20));
add(new ExcelExportEntity("所需器材", "equip", 20));
// add(new ExcelExportEntity("是否展示才艺", "isShowSkillDesc", 20));
// add(new ExcelExportEntity("才艺名称", "skillName", 20));
// add(new ExcelExportEntity("所需器材", "equip", 20));
add(new ExcelExportEntity("交通方式", "traffic", 20));
add(new ExcelExportEntity("自驾车牌号", "carNo", 20));
add(new ExcelExportEntity("是否接站", "isStationDesc", 20));
add(new ExcelExportEntity("是否参加嘉年华", "isPartyDesc", 20));
}};
@@ -139,6 +139,22 @@ public class ActUser extends BaseModel {
@ColDefine(type = ColType.VARCHAR, width = 100)
private String equip;
@Column
@Comment("交通方式")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String traffic;
@Column
@Comment("是否接站")
@ColDefine(type = ColType.BOOLEAN)
@Default("0")
private Boolean isStation;
@Column
@Comment("自驾车牌号")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String carNo;
@Column
@Comment("是否参加嘉年华")
@ColDefine(type = ColType.BOOLEAN)
@@ -26,12 +26,17 @@ public class ActivityItem extends BaseModel {
@ColDefine(type = ColType.VARCHAR, width = 30)
private String name;
@Comment("活动形式")
@Comment("比赛方法")
@Column
@ColDefine(type = ColType.VARCHAR, width = 300)
private String form;
@Comment("评分规则")
@Comment("比赛规则")
@Column
@ColDefine(type = ColType.VARCHAR, width = 500)
private String ruleForm;
@Comment("评分标准")
@Column
@ColDefine(type = ColType.VARCHAR, width = 300)
private String rule;
@@ -47,18 +47,18 @@ public class ActUserServiceImpl extends BaseServiceImpl<ActUser> implements ActU
WHEN 1 THEN '住宿'
WHEN 0 THEN '不住宿'
END AS isStayDesc,
CASE u.isGrant
CASE u.isGrant
WHEN 1 THEN '已发放'
WHEN 0 THEN '未发放'
END AS isGrantDesc,
CASE u.isShowSkill
WHEN 1 THEN '是'
WHEN 0 THEN ''
END AS isShowSkillDesc,
CASE u.isParty
WHEN 1 THEN '是'
WHEN 0 THEN ''
END AS isPartyDesc,
CASE u.isStation
WHEN 1 THEN '是'
WHEN 0 THEN ''
END AS isStationDesc,
CASE u.isParty
WHEN 1 THEN '是'
WHEN 0 THEN ''
END AS isPartyDesc,
act.`title` AS activityName
FROM
act_user u
@@ -1,97 +1,331 @@
const itemForm = {
template: /*language=HTML*/ `
<el-dialog title="项目信息" :visible.sync="visible" width="70%">
<el-dialog title="项目信息" :visible.sync="visible" width="80%" :close-on-click-modal="false"
:before-close="handleClose">
<el-form :model="form" :rules="rules" ref="form" label-width="0">
<el-form-item label="">
<el-table :data="form.tableData" border>
<el-table-column label="序号" type="index" width="50px"></el-table-column>
<el-table-column label="项目名称">
<template #default="{row}">
<el-input v-model="row.name" placeholder="请输入项目名称"></el-input>
</template>
</el-table-column>
<el-table-column label="活动形式">
<template #default="{row}">
<el-input v-model="row.form" placeholder="请输入活动形式"></el-input>
</template>
</el-table-column>
<el-table-column label="评分规则">
<template #default="{row}">
<el-input v-model="row.rule" placeholder="请输入评分规则"></el-input>
</template>
</el-table-column>
<el-table-column label="是否团队合作">
<template #default="{row}">
<el-radio-group v-model="row.isTeamApply" size="medium" @change="row.num=0">
<el-radio-button :label="true">是</el-radio-button>
<el-radio-button :label="false">否</el-radio-button>
</el-radio-group>
</template>
</el-table-column>
<el-table-column label="报名人数">
<template #default="{row}">
<el-input-number v-model="row.num" :disabled="row.isTeamApply"
placeholder="请输入报名人数" style="width: 100%"></el-input-number>
</template>
</el-table-column>
<el-table-column label="图片">
<template #default="{row}">
<image-upload v-model="row.img" :maxCount="1"></image-upload>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="100px">
<template #default="{$index}">
<el-button type="text" class="text-danger" @click="removeRow($index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-button @click="addRow" size="medium" type="primary" class="mt-3 el-icon-plus">添加项目
</el-button>
</el-form-item>
<div v-for="(item, index) in form.tableData" :key="index" class="project-card">
<div class="project-card-header">
<div class="project-card-title">项目 {{index + 1}}</div>
<el-button type="danger" size="mini" icon="el-icon-delete" circle
@click="removeRow(index)"></el-button>
</div>
<el-row class="mt-3 mb-3 pr-3">
<el-form-item
:prop="'tableData.' + index + '.name'"
:rules="[
{ required: true, message: '项目名称不能为空', trigger: 'blur' },
{ max: 50, message: '项目名称长度不能超过50个字符', trigger: 'blur' }
]"
label="项目名称"
label-width="150px"
>
<el-input v-model="item.name" placeholder="请输入项目名称" maxlength="50"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="是否团队合作" label-width="150px">
<el-radio-group v-model="item.isTeamApply" size="medium" @change="item.num=0">
<el-radio-button :label="true">是</el-radio-button>
<el-radio-button :label="false">否</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
:prop="'tableData.' + index + '.num'"
:rules="[
{ required: !item.isTeamApply, message: '报名人数不能为空', trigger: 'blur' },
{ type: 'number', min: 1, message: '报名人数必须大于0', trigger: 'blur' }
]"
label="报名人数"
label-width="150px"
>
<el-input-number
v-model="item.num"
:disabled="item.isTeamApply"
:min="1"
controls-position="right"
placeholder="请输入报名人数"
style="width: 120px">
</el-input-number>
</el-form-item>
</el-row>
<el-tabs type="border-card">
<el-tab-pane label="比赛方法">
<el-form-item
:prop="'tableData.' + index + '.form'"
:rules="[
{ required: true, message: '比赛方法不能为空', trigger: 'blur' },
]"
>
<el-input v-model="item.form" type="textarea" :rows="4" placeholder="请输入比赛方法"
maxlength="500" show-word-limit></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="比赛规则">
<el-form-item
:prop="'tableData.' + index + '.ruleForm'"
:rules="[
{ required: true, message: '比赛规则不能为空', trigger: 'blur' },
]"
>
<el-input v-model="item.ruleForm" type="textarea" :rows="4" placeholder="请输入比赛规则"
maxlength="500" show-word-limit></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="评分标准">
<el-form-item
:prop="'tableData.' + index + '.rule'"
:rules="[
{ required: true, message: '评分标准不能为空', trigger: 'blur' },
]"
>
<el-input v-model="item.rule" type="textarea" :rows="4" placeholder="请输入评分标准"
maxlength="500" show-word-limit></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="项目图片">
<el-form-item>
<image-upload v-model="item.img" :maxCount="1"></image-upload>
<div class="image-tip" v-if="!item.img">
<i class="el-icon-info"></i> 推荐上传 4:3 比例的图片,大小不超过2MB
</div>
</el-form-item>
</el-tab-pane>
</el-tabs>
</div>
<div v-if="form.tableData.length === 0" class="empty-state">
<i class="el-icon-document"></i>
<p>暂无项目,请点击下方按钮添加</p>
</div>
<!-- 添加项目按钮 -->
<el-button @click="addRow" size="medium" type="primary" class="mt-3 el-icon-plus"
:disabled="form.tableData.length >= 20">添加项目
</el-button>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</template>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="onSubmit" :loading="submitting">保存</el-button>
</div>
</el-dialog>
`,
data() {
return {
visible: false,
submitting: false,
form: {
tableData: []
},
originalData: [], // 用于存储原始数据,以便检测变更
rules: {}
}
},
methods: {
onOpen(id) {
this.visible = true
this.resetForm()
this.fetchItems(id)
},
fetchItems(id) {
$.post("/platform/activity/manage/getItems", { id }).then((res) => {
if (res.code === 0) {
this.$set(this.form, "id", id)
this.$set(this.form, "tableData", res.data)
const data = res.data || []
// 确保每个项目都有必要的初始属性
const formattedData = data.map(item => ({
...item,
isTeamApply: item.isTeamApply === undefined ? false : item.isTeamApply,
num: item.num || 0,
form: item.form || "",
ruleForm: item.ruleForm || "",
rule: item.rule || "",
img: item.img || ""
}))
this.$set(this.form, "tableData", formattedData)
this.originalData = JSON.parse(JSON.stringify(formattedData)) // 保存原始数据的副本
} else {
this.$message.error(res.msg || "加载项目数据失败")
}
}).catch(err => {
this.$message.error("网络错误,请稍后重试")
console.error(err)
})
},
addRow() {
this.form.tableData.push({isTeamApply:false,applyNum:0})
},
removeRow(index) {
this.form.tableData.splice(index, 1)
},
onSubmit() {
$.post("/platform/activity/manage/updateItem", {
id: this.form.id,
items: JSON.stringify(this.form.tableData)
}).then((res) => {
if (res.code === 0) {
this.$message.success("修改成功")
this.visible = false
} else {
this.$message.error(res.msg)
if (this.form.tableData.length >= 20) {
this.$message.warning("最多添加20个项目")
return
}
this.form.tableData.push({
name: "",
isTeamApply: false,
num: 1,
form: "",
ruleForm: "",
rule: "",
img: ""
})
// 添加新行后滚动到底部
this.$nextTick(() => {
const container = document.querySelector(".el-dialog__body")
if (container) {
container.scrollTop = container.scrollHeight
}
})
},
removeRow(index) {
this.$confirm("确定要删除此项目吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.form.tableData.splice(index, 1)
this.$message.success("删除成功")
}).catch(() => {
})
},
onSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
if (this.form.tableData.length === 0) {
this.$message.warning("请至少添加一个项目")
return
}
this.submitting = true
// 检查数据是否有变更
const hasChanges = JSON.stringify(this.form.tableData) !== JSON.stringify(this.originalData)
if (!hasChanges) {
this.$message.info("数据未变更")
this.submitting = false
this.visible = false
return
}
$.post("/platform/activity/manage/updateItem", {
id: this.form.id,
items: JSON.stringify(this.form.tableData)
}).then((res) => {
this.submitting = false
if (res.code === 0) {
this.$message.success("保存成功")
this.visible = false
this.$emit("refresh") // 通知父组件刷新数据
} else {
this.$message.error(res.msg || "保存失败")
}
}).catch(err => {
this.submitting = false
this.$message.error("网络错误,请稍后重试")
console.error(err)
})
} else {
this.$message.warning("请完善表单信息")
return false
}
})
},
resetForm() {
this.form = {
id: null,
tableData: []
}
this.originalData = []
this.submitting = false
if (this.$refs.form) {
this.$refs.form.resetFields()
}
},
handleClose() {
// 检查数据是否有变更
const hasChanges = JSON.stringify(this.form.tableData) !== JSON.stringify(this.originalData)
if (hasChanges) {
this.$confirm("有未保存的更改,确定要关闭吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.visible = false
this.resetForm()
}).catch(() => {
})
} else {
this.visible = false
this.resetForm()
}
}
}
},
style: /*language=CSS*/ `
.project-card {
margin-bottom: 20px;
border: 1px solid #EBEEF5;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
background-color: #fff;
transition: all 0.3s;
}
.project-card:hover {
box-shadow: 0 4px 15px 0 rgba(0, 0, 0, 0.15);
}
.project-card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
border-bottom: 1px solid #EBEEF5;
background-color: #f5f7fa;
border-radius: 4px 4px 0 0;
}
.project-card-title {
font-size: 16px;
font-weight: bold;
color: #303133;
}
.el-tabs__content {
padding: 15px;
}
.image-tip {
color: #909399;
font-size: 12px;
margin-top: 8px;
}
.empty-state {
text-align: center;
padding: 40px 0;
color: #909399;
}
.empty-state i {
font-size: 48px;
margin-bottom: 10px;
}
.empty-state p {
font-size: 14px;
}
.el-input-number.is-controls-right .el-input__inner {
padding-left: 15px;
padding-right: 50px;
}
.el-dialog__body {
max-height: calc(100vh - 215px);
overflow-y: auto;
padding: 20px 20px 10px;
}
.project-card .el-tabs--border-card{
border: none;
}
`
}
@@ -97,16 +97,19 @@ layout("/layouts/platform_1.html"){
{{row.isStay?'住宿':'不住宿'}}
</template>
</el-table-column>
<el-table-column label="才艺名称" prop="skillName">
<template slot-scope="{row}">
<span>{{row.isShowSkill && row.skillName?row.skillName:'--'}}</span>
</template>
</el-table-column>
<el-table-column label="所需器材" prop="equip">
<template slot-scope="{row}">
<span>{{row.isShowEquip && row.equip?row.equip:'--'}}</span>
</template>
</el-table-column>
<el-table-column label="交通方式" prop="traffic"></el-table-column>
<el-table-column label="自驾车牌号" prop="carNo"></el-table-column>
<el-table-column label="是否接站" prop="isStationDesc"></el-table-column>
<!-- <el-table-column label="才艺名称" prop="skillName">-->
<!-- <template slot-scope="{row}">-->
<!-- <span>{{row.isShowSkill && row.skillName?row.skillName:'&#45;&#45;'}}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="所需器材" prop="equip">-->
<!-- <template slot-scope="{row}">-->
<!-- <span>{{row.isShowEquip && row.equip?row.equip:'&#45;&#45;'}}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="是否参加嘉年华" prop="isParty">
<template slot-scope="{row}">
{{row.isParty ? '是':''}}
@@ -97,16 +97,14 @@ layout("/layouts/platform_1.html"){
{{row.isStay?'住宿':'不住宿'}}
</template>
</el-table-column>
<el-table-column label="才艺名称" prop="skillName">
<template slot-scope="{row}">
<span>{{row.isShowSkill && row.skillName?row.skillName:'--'}}</span>
</template>
</el-table-column>
<el-table-column label="所需器材" prop="equip">
<template slot-scope="{row}">
<span>{{row.isShowEquip && row.equip?row.equip:'--'}}</span>
</template>
</el-table-column>
<el-table-column label="交通方式" prop="traffic"></el-table-column>
<el-table-column label="自驾车牌号" prop="carNo"></el-table-column>
<el-table-column label="是否接站" prop="isStationDesc"></el-table-column>
<!-- <el-table-column label="所需器材" prop="equip">-->
<!-- <template slot-scope="{row}">-->
<!-- <span>{{row.isShowEquip && row.equip?row.equip:'&#45;&#45;'}}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="是否参加嘉年华" prop="isParty">
<template slot-scope="{row}">
{{row.isParty ? '是':''}}