项目完成人数改为范围值和单值均可

This commit is contained in:
马梓彭 2026-06-10 13:26:00 +08:00
parent 2fec32267d
commit 72c47d1c41
3 changed files with 170 additions and 12 deletions

View File

@ -155,7 +155,13 @@
{{ scope.row.projectTypeName }}
</template>
<template #completionCount="scope">
{{ scope.row.completionCount }}
<template v-if="scope.row.completionCountDisplay">{{ scope.row.completionCountDisplay }}</template>
<template v-else-if="scope.row.completionCountType === 1">
{{ scope.row.completionCountMin ?? 0 }}-{{ scope.row.completionCountMax ?? 0 }}人
</template>
<template v-else>
{{ scope.row.completionCount ?? 0 }}人
</template>
</template>
</ProTable>
<template #footer>

View File

@ -18,7 +18,13 @@
</template>
<template #completionCount="scope">
{{ scope.row.completionCount }}
<span v-if="scope.row.completionCountDisplay">{{ scope.row.completionCountDisplay }}</span>
<span v-else-if="scope.row.completionCountType === 1">
{{ scope.row.completionCountMin }}-{{ scope.row.completionCountMax }}人
</span>
<span v-else>
{{ scope.row.completionCount ?? 0 }}
</span>
</template>
<template #action="scope">
@ -54,11 +60,28 @@
</el-select>
</el-form-item>
<!-- 完成人数 -->
<el-form-item label="完成人数:" prop="completionCount">
<!-- 完成人数模式切换 -->
<el-form-item label="完成人数模式:" prop="completionCountType">
<el-radio-group v-model="formData.completionCountType" @change="onCompletionCountTypeChange">
<el-radio :value="0">单一值</el-radio>
<el-radio :value="1">范围值</el-radio>
</el-radio-group>
</el-form-item>
<!-- 单一值模式:完成人数 -->
<el-form-item v-if="formData.completionCountType === 0" label="完成人数:" prop="completionCount">
<el-input-number v-model="formData.completionCount" placeholder="请输入完成人数" :min="0" :step="1" style="width: 100%"></el-input-number>
</el-form-item>
<!-- 范围值模式:最小和最大完成人数 -->
<el-form-item v-if="formData.completionCountType === 1" label="完成人数范围:" prop="completionCountRange">
<div style="display: flex; align-items: center; gap: 12px; width: 100%">
<el-input-number v-model="formData.completionCountMin" placeholder="最小值" :min="0" :step="1" style="width: 200px"></el-input-number>
<span style="color: #606266">~</span>
<el-input-number v-model="formData.completionCountMax" placeholder="最大值" :min="0" :step="1" style="width: 200px"></el-input-number>
</div>
</el-form-item>
<!-- 组别 -->
<div>
<el-form-item style="display: none;" prop="groups">
@ -146,11 +169,28 @@
</el-select>
</el-form-item>
<!-- 完成人数 -->
<el-form-item label="完成人数:">
<!-- 完成人数模式 -->
<el-form-item label="完成人数模式:">
<el-radio-group v-model="detailData.completionCountType" disabled>
<el-radio :value="0">单一值</el-radio>
<el-radio :value="1">范围值</el-radio>
</el-radio-group>
</el-form-item>
<!-- 单一值模式:完成人数 -->
<el-form-item v-if="detailData.completionCountType === 0" label="完成人数:">
<el-input-number v-model="detailData.completionCount" disabled :min="0" :step="1" style="width: 100%"></el-input-number>
</el-form-item>
<!-- 范围值模式:最小和最大完成人数 -->
<el-form-item v-if="detailData.completionCountType === 1" label="完成人数范围:">
<div style="display: flex; align-items: center; gap: 12px; width: 100%">
<el-input-number v-model="detailData.completionCountMin" disabled :min="0" :step="1" style="width: 200px"></el-input-number>
<span style="color: #606266">~</span>
<el-input-number v-model="detailData.completionCountMax" disabled :min="0" :step="1" style="width: 200px"></el-input-number>
</div>
</el-form-item>
<!-- 组别 -->
<div class="detail-groups-section">
<el-form-item :label="'组别' + (index + 1) + ':'"
@ -243,7 +283,10 @@ const removeGroup = (index) => {
const formData = ref({
name: '',
projectType: '',
completionCountType: 0, // 0=单一值, 1=范围值
completionCount: '',
completionCountMin: '',
completionCountMax: '',
fee: '',
durationMinutes: '',
durationSeconds: '',
@ -257,6 +300,18 @@ const formData = ref({
],
});
// 模式切换处理
const onCompletionCountTypeChange = () => {
if (formData.value.completionCountType === 0) {
// 切换到单一值模式,清空范围值字段
formData.value.completionCountMin = '';
formData.value.completionCountMax = '';
} else {
// 切换到范围值模式,清空单一值字段
formData.value.completionCount = '';
}
};
const validateDuration = (rule, value, callback) => {
const minutes = Number(formData.value.durationMinutes ?? 0);
const seconds = Number(formData.value.durationSeconds ?? 0);
@ -292,10 +347,41 @@ const validateGroups = (rule, value, callback) => {
callback();
};
// 验证完成人数
const validateCompletionCount = (rule, value, callback) => {
if (formData.value.completionCountType === 0) {
// 单一值模式
if (formData.value.completionCount === '' || formData.value.completionCount === null || formData.value.completionCount === undefined) {
callback(new Error('请输入完成人数'));
} else if (Number(formData.value.completionCount) < 0) {
callback(new Error('完成人数不能小于0'));
} else {
callback();
}
} else {
// 范围值模式
const min = formData.value.completionCountMin;
const max = formData.value.completionCountMax;
if (min === '' || min === null || min === undefined) {
callback(new Error('请输入最小值'));
} else if (max === '' || max === null || max === undefined) {
callback(new Error('请输入最大值'));
} else if (Number(min) < 0 || Number(max) < 0) {
callback(new Error('完成人数不能小于0'));
} else if (Number(min) > Number(max)) {
callback(new Error('最小值不能大于最大值'));
} else {
callback();
}
}
};
const formRules = ref({
name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
projectType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
completionCount: [{ required: true, message: '请输入完成人数', trigger: 'blur' }],
completionCountType: [{ required: true, message: '请选择完成人数模式', trigger: 'change' }],
completionCount: [{ required: true, validator: validateCompletionCount, trigger: ['blur', 'change'] }],
completionCountRange: [{ required: true, validator: validateCompletionCount, trigger: ['blur', 'change'] }],
fee: [{ required: true, message: '请输入费用', trigger: 'blur' }],
duration: [
{ required: true, validator: validateDuration, trigger: ['blur', 'change'] }
@ -358,7 +444,10 @@ const onOpenMenu = async (row) => {
formData.value = {
name: '',
projectType: '',
completionCountType: 0, // 默认为单一值模式
completionCount: '',
completionCountMin: '',
completionCountMax: '',
fee: '',
durationMinutes: '',
durationSeconds: '',
@ -374,6 +463,10 @@ const onOpenMenu = async (row) => {
if (row) {
const { succeeded, data } = await projectDetailGet({ id: row.id });
formData.value = data;
// 确保 completionCountType 字段存在(向后兼容:旧数据默认为单一值模式)
if (formData.value.completionCountType === null || formData.value.completionCountType === undefined) {
formData.value.completionCountType = 0;
}
// 确保 groups 数组存在且有效
if (!formData.value.groups || !Array.isArray(formData.value.groups)) {
formData.value.groups = [
@ -414,6 +507,11 @@ const onOpenMenu = async (row) => {
const onViewDetail = async (row) => {
const { succeeded, data } = await projectDetailGet({ id: row.id });
if (succeeded) {
// 确保 completionCountType 字段存在(向后兼容:旧数据默认为单一值模式)
if (data.completionCountType === null || data.completionCountType === undefined) {
data.completionCountType = 0;
}
// 确保 groups 数组存在且有效,并格式化日期
let groupsData = [];
if (data.groups && Array.isArray(data.groups)) {
@ -489,7 +587,15 @@ const onSubmit = () => {
try {
let res;
// 根据模式处理完成人数字段
if (formData.value.completionCountType === 0) {
// 单一值模式
formData.value.completionCount = Number(formData.value.completionCount);
} else {
// 范围值模式
formData.value.completionCountMin = Number(formData.value.completionCountMin);
formData.value.completionCountMax = Number(formData.value.completionCountMax);
}
if (formData.value.id) {
res = await projectEditPut(formData.value);
} else {

View File

@ -421,7 +421,15 @@
人</div> -->
<div class="project-card-type">类型:{{ project.parentProjectTypeName ??
project.projectTypeName ?? '' }}</div>
<div class="project-card-count">完成人数:{{ project.completionCount ?? 0 }}</div>
<div class="project-card-count">完成人数:
<template v-if="project.completionCountDisplay">{{ project.completionCountDisplay }}</template>
<template v-else-if="project.completionCountType === 1">
{{ project.completionCountMin ?? 0 }}-{{ project.completionCountMax ?? 0 }}人
</template>
<template v-else>
{{ project.completionCount ?? 0 }}人
</template>
</div>
</div>
<div class="project-card-right">
<div v-for="g in (project.groups ?? [])" :key="g.id" class="group-tag"
@ -473,7 +481,7 @@
<span>
({{ group.parentProjectTypeName ?? group.projectTypeName ??
(group.projectTeamSize > 1 ?
'团队' : '个人') }}/{{ group.projectCompletionCount ?? 0 }})
'团队' : '个人') }}/{{ group.projectCompletionCountDisplay }})
{{ group.projectName }}-{{ group.groupName ?? group.name }}/{{
formatGroupDate(group) }}/{{
formatGender(group.gender) }}
@ -1006,13 +1014,29 @@ const formatRefundRulesBrief = (refundRules) => {
const detailProjectsForDisplay = computed(() => {
const list = [];
(detailData.value?.projects ?? []).forEach((p) => {
// 统一生成完成人数显示文本
let completionCountDisplay = '';
if (p.completionCountDisplay) {
completionCountDisplay = p.completionCountDisplay;
} else if (p.completionCountType === 1) {
const min = p.completionCountMin ?? 0;
const max = p.completionCountMax ?? 0;
completionCountDisplay = `${min}-${max}人`;
} else {
completionCountDisplay = `${p.completionCount ?? 0}人`;
}
(p.groups ?? []).forEach((g) => {
list.push({
projectName: p.name,
groupName: g.groupName,
fee: p.fee,
limitCount: p.limitCount,
completionCount: p.completionCount
completionCount: p.completionCount,
completionCountType: p.completionCountType ?? 0,
completionCountMin: p.completionCountMin,
completionCountMax: p.completionCountMax,
completionCountDisplay: completionCountDisplay
});
});
// 如果没有组别,只显示项目
@ -1022,7 +1046,11 @@ const detailProjectsForDisplay = computed(() => {
groupName: '-',
fee: p.fee,
limitCount: p.limitCount,
completionCount: p.completionCount
completionCount: p.completionCount,
completionCountType: p.completionCountType ?? 0,
completionCountMin: p.completionCountMin,
completionCountMax: p.completionCountMax,
completionCountDisplay: completionCountDisplay
});
}
});
@ -1210,12 +1238,30 @@ const allGroups = computed(() => {
const list = [];
(projects.value ?? []).forEach((p) => {
(p.groups ?? []).forEach((g) => {
// 生成完成人数显示文本(统一逻辑,确保前端/后端一致)
let completionCountDisplay = '';
if (p.completionCountDisplay) {
completionCountDisplay = p.completionCountDisplay;
} else if (p.completionCountType === 1) {
// 范围值模式
const min = p.completionCountMin ?? 0;
const max = p.completionCountMax ?? 0;
completionCountDisplay = `${min}-${max}人`;
} else {
// 单一值模式
completionCountDisplay = `${p.completionCount ?? 0}人`;
}
list.push({
...g,
projectId: p.id,
projectName: p.name,
projectTeamSize: p.teamSize ?? 1,
projectCompletionCount: p.completionCount ?? 0,
projectCompletionCountType: p.completionCountType ?? 0,
projectCompletionCountMin: p.completionCountMin ?? 0,
projectCompletionCountMax: p.completionCountMax ?? 0,
projectCompletionCountDisplay: completionCountDisplay,
parentProjectTypeName: p.parentProjectTypeName,
projectTypeName: p.projectTypeName,
projectType: p.projectType,