update:报名bug修复
This commit is contained in:
parent
851df6d408
commit
43aaeedc31
2
.env
2
.env
@ -8,4 +8,4 @@ VITE_OPEN = true
|
||||
VITE_OPEN_CDN = false
|
||||
|
||||
# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
|
||||
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202603250222/'
|
||||
VITE_PUBLIC_PATH = 'https://yuedong-wechatapplet.oss-cn-shanghai.aliyuncs.com/static/event_web/202603261000/'
|
||||
@ -5,52 +5,114 @@
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span><span style="color: red;">*</span> 项目配置</span>
|
||||
<el-button type="primary" plain icon="ele-Plus" @click="addProject">选择项目</el-button>
|
||||
<el-button type="primary" plain @click="addProject">选择项目</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-collapse>
|
||||
<el-collapse-item v-for="(item, index) in localFormData.projects" :key="item.projectId ?? item.id ?? index">
|
||||
<template #title>
|
||||
<div class="project-collapse-title">
|
||||
<span>项目{{ index + 1 }}:{{ item.name }}</span>
|
||||
<span class="project-collapse-title__label">限报数</span>
|
||||
<el-input-number v-model="item.limitCount" :min="0" :step="1" :precision="0" :controls="true"
|
||||
@click.stop />
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions>
|
||||
<el-descriptions-item label="类型">{{ item.projectTypeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="时长">{{ item.durationMinutes }}:{{ item.durationSeconds
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="费用">{{ item.fee }}</el-descriptions-item>
|
||||
<el-descriptions-item :label="`组别${idx + 1}:`" v-for="(group, idx) in item.groups">
|
||||
<el-tag>{{ group.groupName }}</el-tag>
|
||||
<span style="margin: 0 10px;">{{ group.birthDateStart }} -- {{ group.birthDateEnd
|
||||
}}</span>
|
||||
<span>{{ genderList[group.gender] }}</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<div class="project-card" v-for="(item, index) in localFormData.projects"
|
||||
:key="item.projectId ?? item.id ?? index">
|
||||
<div class="project-card__meta">
|
||||
<div class="project-card__meta-name">{{ item.name }}</div>
|
||||
<div class="project-card__meta-line">类型:{{ item.projectTypeName }}</div>
|
||||
<div class="project-card__meta-line">时长: {{ item.durationMinutes ?? 0 }}分 {{ item.durationSeconds ?? 0 }}秒</div>
|
||||
<div class="project-card__meta-line meta-muted">费用:{{ item.fee }} 元</div>
|
||||
</div>
|
||||
|
||||
<div class="project-card__groups">
|
||||
<div v-for="(group, gIndex) in (item.groups ?? [])"
|
||||
:key="group.projectGroupId ?? group.id ?? gIndex" class="group-row">
|
||||
<div class="group-row__fields">
|
||||
<el-input v-model="group.groupName" class="group-row__name" placeholder="组别名称" />
|
||||
|
||||
<el-date-picker class="group-row__range" type="daterange" range-separator="~"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:model-value="[group.birthDateStart, group.birthDateEnd]"
|
||||
@update:modelValue="(v) => { group.birthDateStart = v?.[0]; group.birthDateEnd = v?.[1]; }" />
|
||||
|
||||
<el-select v-model="group.gender" class="group-row__gender" placeholder="性别">
|
||||
<el-option label="全部" :value="0" />
|
||||
<el-option label="男" :value="1" />
|
||||
<el-option label="女" :value="2" />
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="group-row__actions">
|
||||
<el-popconfirm title="确认删除该组别吗?" @confirm="removeGroup(index, gIndex)">
|
||||
<template #reference>
|
||||
<el-button text type="danger" icon="ele-Delete">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!(item.groups ?? []).length" class="group-empty">暂无组别</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>限报配置</template>
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="个人项目限报数" prop="registrationLimit.individualProjectLimit">
|
||||
<el-input-number v-model="localFormData.registrationLimit.individualProjectLimit" :min="0"
|
||||
:step="1" />
|
||||
<div v-if="localFormData.projects?.length" class="project-limit-section">
|
||||
<div class="project-limit-section__header">
|
||||
<div class="project-limit-section__title">
|
||||
<span class="required-star">*</span>
|
||||
项目限报配置
|
||||
</div>
|
||||
<div class="project-limit-section__desc">为每个项目设置单独的限报数(必填)</div>
|
||||
</div>
|
||||
|
||||
<div class="project-limit-table">
|
||||
<el-table :data="localFormData.projects" stripe style="width: 100%">
|
||||
<el-table-column label="项目" min-width="220">
|
||||
<template #default="{ row, $index }">
|
||||
<div class="project-limit-name">
|
||||
<div class="project-limit-name__idx">#{{ $index + 1 }}</div>
|
||||
<div class="project-limit-name__text">{{ row.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="限报数" width="220" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item
|
||||
:prop="`projects.${$index}.limitCount`"
|
||||
:rules="[{ required: true, message: '请填写项目限报数', trigger: 'change' }]"
|
||||
style="margin: 0; justify-content: center;"
|
||||
>
|
||||
<el-input-number v-model="row.limitCount" :min="0" :step="1" :precision="0" :controls="true" class="project-limit-input" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="limit-summary">
|
||||
<div class="limit-summary__card">
|
||||
<div class="limit-summary__label">
|
||||
<span class="required-star">*</span>
|
||||
个人项目限报数
|
||||
</div>
|
||||
<el-form-item
|
||||
prop="registrationLimit.individualProjectLimit"
|
||||
:rules="[{ required: true, message: '请填写个人项目限报数', trigger: 'change' }]"
|
||||
style="margin: 0"
|
||||
>
|
||||
<el-input-number v-model="localFormData.registrationLimit.individualProjectLimit" :min="0" :step="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="团队项目限报数" prop="registrationLimit.teamProjectLimit">
|
||||
<el-input-number v-model="localFormData.registrationLimit.teamProjectLimit" :min="0"
|
||||
:step="1" />
|
||||
</div>
|
||||
<div class="limit-summary__card">
|
||||
<div class="limit-summary__label">
|
||||
<span class="required-star">*</span>
|
||||
团队项目限报数
|
||||
</div>
|
||||
<el-form-item
|
||||
prop="registrationLimit.teamProjectLimit"
|
||||
:rules="[{ required: true, message: '请填写团队项目限报数', trigger: 'change' }]"
|
||||
style="margin: 0"
|
||||
>
|
||||
<el-input-number v-model="localFormData.registrationLimit.teamProjectLimit" :min="0" :step="1" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form>
|
||||
|
||||
@ -167,6 +229,13 @@ const columns = ref([
|
||||
|
||||
|
||||
const removeProject = (idx) => localFormData.value.projects.splice(idx, 1);
|
||||
const removeGroup = (projectIndex, groupIndex) => {
|
||||
const p = localFormData.value.projects?.[projectIndex];
|
||||
if (!p) return;
|
||||
if (!Array.isArray(p.groups)) p.groups = [];
|
||||
p.groups.splice(groupIndex, 1);
|
||||
ElMessage.success('删除组别成功');
|
||||
};
|
||||
|
||||
const isSyncingFromParent = ref(false);
|
||||
|
||||
@ -241,23 +310,172 @@ defineExpose({ validate });
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.project-collapse-title {
|
||||
.project-limit-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.project-limit-section__header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.project-limit-section__title {
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.project-limit-section__desc {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.required-star {
|
||||
color: var(--el-color-danger);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.project-limit-table {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.project-limit-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.project-collapse-title__label {
|
||||
color: var(--el-text-color-secondary);
|
||||
.project-limit-name__idx {
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
margin-left: 40px;
|
||||
color: var(--el-text-color-secondary);
|
||||
background: var(--el-fill-color-light);
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.project-collapse-title .el-input-number {
|
||||
.project-limit-name__text {
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.project-limit-input {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.limit-summary {
|
||||
margin-top: 14px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.limit-summary__card {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 12px;
|
||||
background: var(--el-fill-color-light);
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.limit-summary__label {
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.project-card {
|
||||
display: flex;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.project-card__meta {
|
||||
width: 210px;
|
||||
padding: 16px 14px;
|
||||
background: linear-gradient(180deg, #4f8ffb 0%, #2f73f5 100%);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.project-card__meta-name {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.project-card__meta-line {
|
||||
font-size: 13px;
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.meta-muted {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.project-card__groups {
|
||||
flex: 1;
|
||||
padding: 14px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.group-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 10px;
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.group-row__fields {
|
||||
display: grid;
|
||||
grid-template-columns: 140px minmax(280px, 1fr) 120px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.group-row__name,
|
||||
.group-row__range,
|
||||
.group-row__gender {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.group-row__actions {
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.group-row:hover .group-row__actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.group-empty {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
padding: 6px 2px;
|
||||
}
|
||||
|
||||
.input-hint {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
|
||||
@ -16,11 +16,36 @@
|
||||
|
||||
|
||||
<el-divider content-position="center" style="margin: 60px 0 40px;">账户信息</el-divider>
|
||||
<el-form-item label="收款商户" prop="merchantId" v-if="localFormData.chargeMode !== 0">
|
||||
<el-select v-model="localFormData.merchantId" filterable placeholder="请选择商户(可选)" style="width: 100%">
|
||||
<el-option v-for="m in merchantOptions" :key="m.value" :label="m.label" :value="m.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div v-if="localFormData.chargeMode !== 0" class="account-panel">
|
||||
<el-form-item label="收款商户" prop="merchantId" required style="margin-bottom: 14px;">
|
||||
<el-select v-model="localFormData.merchantId" filterable placeholder="请选择商户" @change="syncMerchantInfo" style="width: 100%">
|
||||
<el-option v-for="m in merchantOptions" :key="m.value" :label="m.label" :value="m.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<div class="account-grid">
|
||||
<div class="account-item">
|
||||
<div class="account-item__label">商户名称</div>
|
||||
<el-input v-model="localFormData.merchantName" disabled placeholder="-" />
|
||||
</div>
|
||||
<div class="account-item">
|
||||
<div class="account-item__label">统一信用代码</div>
|
||||
<el-input v-model="localFormData.creditCode" disabled placeholder="-" />
|
||||
</div>
|
||||
<div class="account-item">
|
||||
<div class="account-item__label">开户银行</div>
|
||||
<el-input v-model="localFormData.bankName" disabled placeholder="-" />
|
||||
</div>
|
||||
<div class="account-item">
|
||||
<div class="account-item__label">银行账号</div>
|
||||
<el-input v-model="localFormData.accountNumber" disabled placeholder="-" />
|
||||
</div>
|
||||
<div class="account-item">
|
||||
<div class="account-item__label">营业执照</div>
|
||||
<img :src="businessLicenseUrl" style="width: 100px; height: 100px;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="开户银行" prop="bankName">
|
||||
@ -48,6 +73,8 @@ const localFormData = ref({
|
||||
chargeMode: 0,
|
||||
price: 0,
|
||||
merchantId: undefined,
|
||||
merchantName: '',
|
||||
creditCode: '',
|
||||
bankName: '',
|
||||
accountNumber: '',
|
||||
});
|
||||
@ -68,21 +95,52 @@ watch(
|
||||
(v) => emit('update:modelValue', { ...props.modelValue, ...v }),
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const businessLicenseUrl = ref('');
|
||||
const merchantOptions = ref([]);
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const res = await merchantPageGet({ PageNo: 1, PageSize: 200 });
|
||||
const rows = res?.data?.rows ?? [];
|
||||
merchantOptions.value = rows.map((m) => ({ label: m.merchantName ?? m.name ?? `${m.id}`, value: m.id }));
|
||||
merchantOptions.value = rows.map((m) => ({
|
||||
label: m.merchantName ?? m.name ?? `${m.id}`,
|
||||
value: m.id,
|
||||
merchantName: m.merchantName ?? m.name ?? '',
|
||||
creditCode: m.creditCode ?? '',
|
||||
bankName: m.bankName ?? '',
|
||||
accountNumber: m.accountNumber ?? '',
|
||||
businessLicenseUrl: m.businessLicenseUrl ?? '',
|
||||
}));
|
||||
} catch {
|
||||
merchantOptions.value = [];
|
||||
}
|
||||
syncMerchantInfo();
|
||||
});
|
||||
|
||||
const syncMerchantInfo = () => {
|
||||
const id = localFormData.value.merchantId;
|
||||
if (!id) {
|
||||
localFormData.value.merchantName = '';
|
||||
localFormData.value.creditCode = '';
|
||||
localFormData.value.bankName = '';
|
||||
localFormData.value.accountNumber = '';
|
||||
return;
|
||||
}
|
||||
// el-select 可能返回 string/number,这里做宽松匹配避免找不到
|
||||
const m = (merchantOptions.value ?? []).find((x) => x?.value == id);
|
||||
localFormData.value.merchantName = m?.merchantName ?? '';
|
||||
localFormData.value.creditCode = m?.creditCode ?? '';
|
||||
localFormData.value.bankName = m?.bankName ?? '';
|
||||
localFormData.value.accountNumber = m?.accountNumber ?? '';
|
||||
businessLicenseUrl.value = m?.businessLicenseUrl ?? '';
|
||||
};
|
||||
|
||||
// watch(() => localFormData.value.merchantId, syncMerchantInfo, { immediate: true , deep: true});
|
||||
watch(merchantOptions, syncMerchantInfo, { deep: true });
|
||||
|
||||
const rules = {
|
||||
chargeMode: [{ required: true, message: '请选择收费模式', trigger: 'change' }],
|
||||
price: [{ required: false, message: '请输入价格', trigger: 'change' }],
|
||||
merchantId: [{ required: true, message: '请选择收款商户', trigger: 'change' }],
|
||||
bankName: [{ required: false, message: '请输入开户银行', trigger: 'blur' }],
|
||||
accountNumber: [{ required: false, message: '请输入银行账号', trigger: 'blur' }],
|
||||
};
|
||||
@ -104,6 +162,33 @@ defineExpose({ validate });
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.account-panel {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.account-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 12px;
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.account-item {
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
}
|
||||
|
||||
.account-item__label {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.fee-type-group {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
@ -266,10 +266,16 @@ const handleSubmit = async () => {
|
||||
const rawProjects = formData.value.projectConfig?.projects ?? [];
|
||||
const projects = rawProjects.map((p) => {
|
||||
// 后端字段要求:projects[].projectId,而不是 projects[].id
|
||||
const { id, projectId: existingProjectId, ...rest } = p ?? {};
|
||||
const { id, projectId: existingProjectId, groups, ...rest } = p ?? {};
|
||||
const mappedGroups = (groups ?? []).map((g) => {
|
||||
// 后端字段要求:groups[].projectGroupId,而不是 groups[].id
|
||||
const { id: groupId, projectGroupId: existingGroupId, ...gRest } = g ?? {};
|
||||
return { ...gRest, projectGroupId: existingGroupId ?? groupId };
|
||||
});
|
||||
return {
|
||||
...rest,
|
||||
projectId: existingProjectId ?? id,
|
||||
groups: mappedGroups,
|
||||
};
|
||||
});
|
||||
const payload = {
|
||||
@ -369,11 +375,6 @@ defineExpose({
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.step-form-card {
|
||||
/* border-radius: 12px;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15); */
|
||||
}
|
||||
|
||||
.card-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user