update:项目管理&赛事管理

This commit is contained in:
ltx 2026-03-19 01:20:23 +08:00
parent 68127a81fa
commit fe000094c3
13 changed files with 628 additions and 68 deletions

View File

@ -84,7 +84,7 @@ export const projectDeleteDelete = (data) => {
* @param {number} params.id - 项目ID
*/
export const projectDetailGet = (params) => {
return http.post('/project/detail', params);
return http.post(`/project/detail/${params.id}`, params);
};
/**

View File

@ -420,7 +420,7 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
},
]
},
{
{
path: '/user',
name: 'user',
component: () => import('/@/views/user/general/index.vue'),
@ -460,6 +460,67 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
},
]
},
{
path: '/integral',
name: "integral",
component: () => import('/@/views/user/general/index.vue'),
meta: {
isKeepAlive: true,
},
children: [
{
path: '/integral/config',
name: 'integralconfig',
component: () => import('/@/views/match/points/config/index.vue'),
meta: {
title: '积分配置',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin', 'common'],
icon: 'iconfont icon-shouye',
},
},
{
path: '/integral/record',
name: 'integralrecord',
component: () => import('/@/views/match/user/unit/index.vue'),
meta: {
isKeepAlive: true,
},
children:[
{
path: '/integral/record/general',
name: 'integralrecordgeneral',
component: () => import('/@/views/match/points/general/index.vue'),
meta: {
title: '用户积分记录',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
}
},
{
path: '/integral/record/unit',
name: 'integralrecordunit',
component: () => import('/@/views/match/points/unit/index.vue'),
meta: {
title: '单位积分记录',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
}
}
]
},
]
},
];
/**

View File

@ -144,7 +144,7 @@ const rules = ref({
});
const handleAvatarSuccess = (response) => {
localFormData.value.coverImage = response?.data ?? response?.url ?? response;
localFormData.value.coverImage = response?.[0]?.url;
};
const validate = async () => {

View File

@ -1,6 +1,6 @@
<template>
<div class="step-units">
<el-form ref="formRef" :model="localFormData" :rules="rules" label-position="right" label-width="120px">
<el-form ref="formRef" :model="localFormData" :rules="rules" label-position="right" label-width="0px">
<el-table :data="localFormData.units" border stripe style="width: 100%">
<el-table-column label="序号" width="80" align="center">
<template #default="{ $index }">{{ $index + 1 }}</template>
@ -8,7 +8,7 @@
<el-table-column label="单位类型" width="180" align="center">
<template #default="{ row, $index }">
<el-form-item :prop="`units.${$index}.unitType`" :rules="[{ required: true, message: '请选择单位类型', trigger: 'change' }]" style="margin: 0">
<el-form-item :prop="`units.${$index}.unitType`" :rules="[{ required: true, message: '请选择单位类型', trigger: 'change' }]" style="margin: 0;width: 100%;">
<el-select v-model="row.unitType" placeholder="请选择" style="width: 100%">
<el-option label="主办方" value="Host" />
<el-option label="承办方" value="Organizer" />
@ -26,13 +26,17 @@
</template>
</el-table-column>
<el-table-column label="LogoUrl" min-width="220" align="center">
<template #default="{ row }">
<el-input v-model="row.logoUrl" placeholder="可不填,填写图片URL" />
<el-table-column label="LogoUrl" min-width="120" align="center">
<template #default="{ row ,$index }">
<!-- <el-input v-model="row.logoUrl" placeholder="可不填,填写图片URL" /> -->
<el-upload class="avatar-uploader" action="/api/file/upload" :show-file-list="false" :on-success=" (response) => handleAvatarSuccess(response, $index)">
<img v-if="row.logoUrl" :src="row.logoUrl" style="height: 120px;" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</template>
</el-table-column>
<el-table-column label="排序" width="120" align="center">
<el-table-column label="排序" width="180" align="center">
<template #default="{ row }">
<el-input-number v-model="row.sort" :min="0" :step="1" />
</template>
@ -80,6 +84,11 @@ watch(
const add = () => {
localFormData.value.units.push({ unitType: '', unitName: '', logoUrl: '', sort: localFormData.value.units.length });
};
const handleAvatarSuccess = (response, index) => {
console.log('handleAvatarSuccess', response,index);
localFormData.value.units[index].logoUrl = response?.[0]?.url;
};
const remove = (idx) => localFormData.value.units.splice(idx, 1);
const rules = {
@ -87,7 +96,12 @@ const rules = {
};
const validate = async () => {
console.log('validate', formRef.value);
if (!formRef.value) return false;
if(!localFormData.value.units.length){
ElMessage.error('请至少添加一个参与单位');
return false;
}
return await formRef.value.validate();
};

View File

@ -96,6 +96,21 @@ const localFormData = ref({
registrationLimit: { individualProjectLimit: 1, teamProjectLimit: 1 },
});
const addProject = () => {
localFormData.value.projects.push({
name: '',
projectTypeId: 0,
projectTypeName: '',
completionCount: 0,
durationMinutes: 0,
durationSeconds: 0,
fee: 0,
limitCount: 0,
groupsText: '',
});
};
const removeProject = (idx) => localFormData.value.projects.splice(idx, 1);
const normalizeFromParent = (v) => {
localFormData.value.registrationLimit = v?.registrationLimit ?? { individualProjectLimit: 1, teamProjectLimit: 1 };
localFormData.value.projects = (v?.projects ?? []).map((p) => ({
@ -141,20 +156,7 @@ watch(
{ deep: true }
);
const addProject = () => {
localFormData.value.projects.push({
name: '',
projectTypeId: 0,
projectTypeName: '',
completionCount: 0,
durationMinutes: 0,
durationSeconds: 0,
fee: 0,
limitCount: 0,
groupsText: '',
});
};
const removeProject = (idx) => localFormData.value.projects.splice(idx, 1);
/* addProject and removeProject are declared above to avoid initialization order issues */
const rules = {
'registrationLimit.individualProjectLimit': [{ required: true, message: '请填写个人项目限报数', trigger: 'change' }],

View File

@ -1,5 +1,5 @@
<template>
<el-dialog title="新增" v-model="dialog.isShowDialog" width="900px">
<el-dialog :title="dialog.title" v-model="dialog.isShowDialog" width="80%">
<div class="step-form-container">
<el-card class="step-form-card">
<!-- 步骤条导航 -->
@ -245,7 +245,7 @@ const handleNext = async () => {
}
} catch (error) {
console.error('验证失败:', error);
ElMessage.error('验证失败,请检查输入');
ElMessage.error(`验证失败,请检查输入`);
}
};

View File

@ -10,7 +10,7 @@
toolButton
>
<template #tools>
<el-button v-auth="'event:add'" type="primary" @click="onOpenMenu"> 新增 </el-button>
<el-button v-auth="'event:add'" type="primary" @click="onOpenMenu()"> 新增 </el-button>
<el-button v-auth="'event:add'" type="primary" @click="onOpenMenu"> 导出 </el-button>
</template>
<template #index="scope">

View File

@ -0,0 +1,222 @@
<template>
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="pointsrulePageGet" :columns="columns" :pagination="true" :tool-button="true">
<template #tools>
<el-button type="primary" @click="onOpenDialog()"> 新增规则 </el-button>
</template>
<template #index="scope">
{{ scope.$index + 1 }}
</template>
<template #action="scope">
<el-button size="small" text type="primary" icon="ele-Edit" @click="onOpenDialog(scope.row)"> 编辑 </el-button>
<!-- <el-button
size="small"
text
:type="scope.row.status === 'Enable' ? 'warning' : 'success'"
@click="onToggleStatus(scope.row)"
>
{{ scope.row.status === 'Enable' ? '禁用' : '启用' }}
</el-button> -->
<el-popconfirm title="确认删除吗?" @confirm="onDelete(scope.row.id)">
<template #reference>
<el-button size="small" text type="danger" icon="ele-Delete"> 删除 </el-button>
</template>
</el-popconfirm>
</template>
</ProTable>
<!-- 弹窗 -->
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="900px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-if="isShowDialog">
<el-form-item label="规则名称" prop="ruleName">
<el-input v-model="formData.ruleName" placeholder="请输入规则名称" />
</el-form-item>
<el-form-item label="参与积分" prop="participationPoints">
<el-input-number v-model="formData.participationPoints" :min="0" :step="1" style="width: 100%" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="可不填" />
</el-form-item>
<el-form-item label="名次积分">
<div style="width: 100%">
<div style="display: flex; justify-content: flex-end; margin-bottom: 10px">
<el-button type="primary" plain icon="ele-Plus" @click="onAddDetailRow">新增区间</el-button>
</div>
<el-table :data="formData.details" border style="width: 100%" >
<el-table-column label="起始排名" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.startRank" :min="1" :step="1" />
</template>
</el-table-column>
<el-table-column label="结束排名" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.endRank" :min="1" :step="1" />
</template>
</el-table-column>
<el-table-column label="对应积分" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.points" :min="0" :step="1" />
</template>
</el-table-column>
<el-table-column label="操作" width="140" align="center">
<template #default="scope">
<el-button text type="danger" icon="ele-Delete" @click="onRemoveDetailRow(scope.$index)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
import ProTable from '/@/components/ProTable/index.vue';
import {
pointsruleAddPost,
pointsruleDeleteDelete,
pointsruleDetailGet,
pointsruleEditPut,
pointsrulePageGet,
pointsruleSetstatusPatch,
} from '/@/api/match/pointsrule';
const tableRef = ref<any>();
const formRef = ref();
const buildEmptyForm = () => ({
id: undefined as number | undefined,
ruleName: '',
participationPoints: 0,
remark: '',
details: [] as Array<{ id?: number; startRank: number; endRank: number; points: number }>,
});
const formData = ref(buildEmptyForm());
const formRules = ref({
ruleName: [{ required: true, message: '请输入规则名称', trigger: 'blur' }],
participationPoints: [{ required: true, message: '请输入参与积分', trigger: 'change' }],
});
const columns = ref([
{ prop: 'index', label: '序号', align: 'center', width: 70 },
{ prop: 'ruleName', label: '规则名称', align: 'center', search: { el: 'input' } },
{ prop: 'participationPoints', label: '参与积分', align: 'center' },
{ prop: 'remark', label: '备注', align: 'center' },
// {
// prop: 'status',
// label: '状态',
// align: 'center',
// enum: [
// { label: '启用', value: 'Enable' },
// { label: '禁用', value: 'Disable' },
// ],
// search: { el: 'select' },
// },
{ prop: 'createdTime', label: '创建时间', align: 'center' },
{ prop: 'action', label: '操作', align: 'center', fixed: 'right', width: 220 },
]);
const isShowDialog = ref(false);
const dialogTitle = ref('新增');
const onOpenDialog = async (row?: any) => {
dialogTitle.value = row ? '编辑' : '新增';
if (row?.id) {
const res: any = await pointsruleDetailGet({ id: row.id });
formData.value = {
id: res.data?.id ?? row.id,
ruleName: res.data?.ruleName ?? row.ruleName ?? '',
participationPoints: res.data?.participationPoints ?? row.participationPoints ?? 0,
remark: res.data?.remark ?? row.remark ?? '',
details: (res.data?.details ?? []).map((d: any) => ({
id: d.id,
startRank: d.startRank,
endRank: d.endRank,
points: d.points,
})),
};
} else {
formData.value = buildEmptyForm();
}
if (!formData.value.details?.length) onAddDetailRow();
isShowDialog.value = true;
};
const onAddDetailRow = () => {
formData.value.details.push({ startRank: 1, endRank: 1, points: 0 });
};
const onRemoveDetailRow = (index: number) => {
formData.value.details.splice(index, 1);
};
const onDelete = async (id: number) => {
await pointsruleDeleteDelete({ id });
ElMessage.success('删除成功');
tableRef.value?.getTableList?.();
};
const onToggleStatus = async (row: any) => {
const next = row.status === 'Enable' ? 'Disable' : 'Enable';
await pointsruleSetstatusPatch({ id: row.id, status: next });
ElMessage.success('操作成功');
tableRef.value?.getTableList?.();
};
// 表单提交
const onSubmit = () => {
if (!formRef.value) return;
formRef.value.validate(async (valid: boolean) => {
if (!valid) return;
if (!formData.value.details?.length) {
ElMessage.warning('请至少配置一个排名区间');
return;
}
const payload = {
id: formData.value.id,
ruleName: formData.value.ruleName,
participationPoints: formData.value.participationPoints,
remark: formData.value.remark,
details: formData.value.details.map((d) => ({
startRank: d.startRank,
endRank: d.endRank,
points: d.points,
})),
};
if (formData.value.id) {
await pointsruleEditPut(payload);
ElMessage.success('编辑成功');
} else {
await pointsruleAddPost(payload);
ElMessage.success('新增成功');
}
isShowDialog.value = false;
tableRef.value?.getTableList?.();
});
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="pointsrecordListGet" @selection-change="handleSelectionChange"
:columns="columns" :pagination="true" :tool-button="false" :initParams="initParam" row-key="userId">
<template #identityInfo="scope">
<el-image style="width: 100px;" :src="scope.row.idCardImageUrl" fit="cover"></el-image>
</template>
<template #action="scope">
<el-button v-auth="'user:general:record'" size="small" text type="primary"
@click="onOpenMenu(scope.row)"> 积分明细 </el-button>
</template>
</ProTable>
<!-- 弹窗 -->
<el-dialog title="积分明细" v-model="isShowDialog" width="80%">
<ProTable ref="table" :request-api="pointsDetailApi" :columns="columnsUser" :pagination="true"
:tool-button="false" :initParam="initParamUser">
<template #points="scope">
<el-tag :type="scope.row.points > 0 ? 'success' : 'danger'">{{ scope.row.points }}</el-tag>
</template>
</ProTable>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onCancel">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="general">
import { defineAsyncComponent, ref, reactive } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import ProTable from '/@/components/ProTable/index.vue';
import { pointsrecordListGet, pointsrecordDetailGet, pointsrecordSetstatusPatch } from '/@/api/match/pointRecord';
import { eventrecordCertificatesGet } from '/@/api/match/eventRecord';
const initParam = ref({
refresh: true,
});
const selectedListIds = ref([]);
const initParamUser = ref({
userId: '',
userType: '0',
});
const statusList = ['info', 'warning', 'success', 'danger'];
const columns = ref([
{ prop: 'name', label: '姓名', search: { el: 'input' } },
{ prop: 'phone', label: '联系电话', search: { el: 'input' } },
{ prop: 'identityInfo', label: '身份证' },
{ prop: 'totalPoints', label: '积分额度' },
{ prop: 'action', label: '操作', align: 'center' },
]);
const tableRef = ref();
const handleSelectionChange = (val) => {
console.log(val);
selectedListIds.value = val.map((item) => item.userId);
};
const columnsUser = ref([
{
prop: 'type',
label: '积分类型',
search: { el: 'select' },
enum: [
{ label: '全部', value: '' },
{ label: '获取', value: 1 },
{ label: '消耗', value: 2 },
],
},
{ prop: 'action', label: '操作',search: { el: 'input' }, },
{ prop: 'item', label: '项目', },
{ prop: 'group', label: '组别', },
{ prop: 'points', label: '积分收支',},
{
prop: 'createdTime',
label: '操作时间',
// search: {
// el: 'date-picker',
// props: { type: 'daterange' },
// },
},
]);
const isShowDialog = ref(false);
const onOpenMenu = (row) => {
// main 表 的 用户 id 字段为 userId
initParamUser.value.userId = row.userId ?? row.id ?? '';
isShowDialog.value = true;
};
// pointsrecordDetailGet 的签名为 (userid, params)
const pointsDetailApi = (params) => {
const userid = initParamUser.value.userId;
return pointsrecordDetailGet(userid, params);
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
/* 时长组合框样式 */
.duration-row {
display: flex;
align-items: center;
gap: 8px;
}
.duration-row .el-input {
width: 120px;
}
.duration-separator {
color: #606266;
font-size: 14px;
}
.duration-label {
color: #909399;
font-size: 14px;
}
</style>

View File

@ -2,21 +2,21 @@
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="pointsrulePageGet" :columns="columns" :pagination="true" :tool-button="true">
<template #tools>
<el-button type="primary" icon="ele-Plus" @click="onOpenDialog()"> 新增规则 </el-button>
<el-button type="primary" @click="onOpenDialog()"> 新增规则 </el-button>
</template>
<template #index="scope">
{{ scope.$index + 1 }}
</template>
<template #action="scope">
<el-button size="small" text type="primary" icon="ele-Edit" @click="onOpenDialog(scope.row)"> 编辑 </el-button>
<el-button
<!-- <el-button
size="small"
text
:type="scope.row.status === 'Enable' ? 'warning' : 'success'"
@click="onToggleStatus(scope.row)"
>
{{ scope.row.status === 'Enable' ? '禁用' : '启用' }}
</el-button>
</el-button> -->
<el-popconfirm title="确认删除吗?" @confirm="onDelete(scope.row.id)">
<template #reference>
<el-button size="small" text type="danger" icon="ele-Delete"> 删除 </el-button>
@ -38,28 +38,28 @@
<el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="可不填" />
</el-form-item>
<el-form-item label="排名区间">
<el-form-item label="名次积分">
<div style="width: 100%">
<div style="display: flex; justify-content: flex-end; margin-bottom: 10px">
<el-button type="primary" plain icon="ele-Plus" @click="onAddDetailRow">新增区间</el-button>
</div>
<el-table :data="formData.details" border>
<el-table-column label="起始排名" width="160">
<el-table :data="formData.details" border style="width: 100%" >
<el-table-column label="起始排名" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.startRank" :min="1" :step="1" />
</template>
</el-table-column>
<el-table-column label="结束排名" width="160">
<el-table-column label="结束排名" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.endRank" :min="1" :step="1" />
</template>
</el-table-column>
<el-table-column label="对应积分" width="160">
<el-table-column label="对应积分" width="180">
<template #default="scope">
<el-input-number v-model="scope.row.points" :min="0" :step="1" />
</template>
</el-table-column>
<el-table-column label="操作" width="120" align="center">
<el-table-column label="操作" width="140" align="center">
<template #default="scope">
<el-button text type="danger" icon="ele-Delete" @click="onRemoveDetailRow(scope.$index)">
删除
@ -116,16 +116,16 @@ const columns = ref([
{ prop: 'ruleName', label: '规则名称', align: 'center', search: { el: 'input' } },
{ prop: 'participationPoints', label: '参与积分', align: 'center' },
{ prop: 'remark', label: '备注', align: 'center' },
{
prop: 'status',
label: '状态',
align: 'center',
enum: [
{ label: '启用', value: 'Enable' },
{ label: '禁用', value: 'Disable' },
],
search: { el: 'select' },
},
// {
// prop: 'status',
// label: '状态',
// align: 'center',
// enum: [
// { label: '启用', value: 'Enable' },
// { label: '禁用', value: 'Disable' },
// ],
// search: { el: 'select' },
// },
{ prop: 'createdTime', label: '创建时间', align: 'center' },
{ prop: 'action', label: '操作', align: 'center', fixed: 'right', width: 220 },
]);

View File

@ -0,0 +1,135 @@
<template>
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="pointsrecordListGet" @selection-change="handleSelectionChange"
:columns="columns" :pagination="true" :tool-button="false" :initParam="initParam" row-key="userId">
<template #action="scope">
<el-button v-auth="'user:general:record'" size="small" text type="primary"
@click="onOpenMenu(scope.row)"> 积分明细 </el-button>
</template>
</ProTable>
<!-- 弹窗 -->
<el-dialog title="积分明细" v-model="isShowDialog" width="80%">
<ProTable ref="table" :request-api="pointsDetailApi" :columns="columnsUser" :pagination="true"
:tool-button="false" :initParam="initParamUser">
<template #points="scope">
<el-tag :type="scope.row.points > 0 ? 'success' : 'danger'">{{ scope.row.points }}</el-tag>
</template>
</ProTable>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onCancel">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="general">
import { defineAsyncComponent, ref, reactive } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import ProTable from '/@/components/ProTable/index.vue';
import { pointsrecordListGet, pointsrecordDetailGet, pointsrecordSetstatusPatch } from '/@/api/match/pointRecord';
import { eventrecordCertificatesGet } from '/@/api/match/eventRecord';
const initParam = ref({
refresh: true,
userType: '1',
});
const selectedListIds = ref([]);
const initParamUser = ref({
userId: '',
userType: '1',
});
const statusList = ['info', 'warning', 'success', 'danger'];
const columns = ref([
{ prop: 'name', label: '单位名称', search: { el: 'input' } },
{ prop: 'phone', label: '联系电话', search: { el: 'input' } },
{ prop: 'identityInfo', label: '统一社会信用代码' },
{ prop: 'totalPoints', label: '积分额度' },
{ prop: 'action', label: '操作', align: 'center' },
]);
const tableRef = ref();
const handleSelectionChange = (val) => {
console.log(val);
selectedListIds.value = val.map((item) => item.userId);
};
const columnsUser = ref([
{
prop: 'type',
label: '积分类型',
search: { el: 'select' },
enum: [
{ label: '全部', value: '' },
{ label: '获取', value: 1 },
{ label: '消耗', value: 2 },
],
},
{ prop: 'action', label: '操作',search: { el: 'input' }, },
{ prop: 'item', label: '项目', },
{ prop: 'group', label: '组别', },
{ prop: 'participantName', label: '参赛人',},
{ prop: 'points', label: '积分收支',},
{
prop: 'createdTime',
label: '操作时间',
// search: {
// el: 'date-picker',
// props: { type: 'daterange' },
// },
},
]);
const isShowDialog = ref(false);
const onOpenMenu = (row) => {
// main 表 的 用户 id 字段为 userId
initParamUser.value.userId = row.userId ?? row.id ?? '';
isShowDialog.value = true;
};
// pointsrecordDetailGet 的签名为 (userid, params)
const pointsDetailApi = (params) => {
const userid = initParamUser.value.userId;
return pointsrecordDetailGet(userid, params);
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
.dialog-footer {
margin-top: 80px;
}
/* 时长组合框样式 */
.duration-row {
display: flex;
align-items: center;
gap: 8px;
}
.duration-row .el-input {
width: 120px;
}
.duration-separator {
color: #606266;
font-size: 14px;
}
.duration-label {
color: #909399;
font-size: 14px;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="projectPageGet" :columns="columns" :pagination="true" :tool-button="false" :initParams="initParam">
<ProTable ref="tableRef" :request-api="projectPageGet" :columns="columns" :pagination="true" :tool-button="false" :initParam="initParam">
<template #tools>
<el-button v-auth="'project:add'" type="primary" icon="ele-Plus" @click="onOpenMenu()"> 新增 </el-button>
</template>
@ -29,7 +29,7 @@
</ProTable>
<!-- 弹窗 -->
<el-dialog title="新增" v-model="isShowDialog" width="60%">
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="60%">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="150px" style="width: 90%; margin-bottom: 30px" v-if="isShowDialog">
<!-- 项目名称 -->
<el-form-item label="项目名称:" prop="name">
@ -60,16 +60,17 @@
:key="index"
:rules="{
validator: (rule, value, callback) => {
if (!value.groupName) {
console.log(value);
if (!value[index].groupName) {
callback(new Error('请输入组别名'));
}
if (!value.birthDateStart) {
if (!value[index].birthDateStart) {
callback(new Error('请选择出生日期开始'));
}
if (!value.birthDateEnd) {
if (!value[index].birthDateEnd) {
callback(new Error('请选择出生日期结束'));
}
if (!value.gender) {
if (!value[index].gender) {
callback(new Error('请选择性别'));
} else {
callback();
@ -132,7 +133,7 @@ import { ElMessage, ElForm } from 'element-plus';
import SysMenuApi from '/@/api/SysMenuApi';
import { auths } from '/@/utils/authFunction';
import ProTable from '/@/components/ProTable/index.vue';
import { projectPageGet, projectAddPost, projectEditPut, projectDeleteDelete } from '/@/api/match/project';
import { projectPageGet, projectAddPost, projectEditPut, projectDeleteDelete , projectDetailGet } from '/@/api/match/project';
// 定义表单引用类型
const formRef = ref();
@ -221,7 +222,7 @@ const columns = ref([
const isShowDialog = ref(false);
const dialogTitle = ref('新增');
const onOpenMenu = (row) => {
const onOpenMenu = async (row) => {
console.log(row);
dialogTitle.value = row ? '编辑' : '新增';
formData.value = {
@ -241,7 +242,8 @@ const onOpenMenu = (row) => {
],
};
if (row) {
formData.value = row;
const { succeeded, data } = await projectDetailGet({ id: row.id });
formData.value = data;
}
isShowDialog.value = true;
};

View File

@ -1,14 +0,0 @@
<template>
<div class="layout-padding">
<h2>用户管理(赛事)</h2>
<p>占位页面:用于修复路由引用缺失导致的启动失败。</p>
</div>
</template>
<script setup lang="ts"></script>
<style scoped lang="scss">
.layout-padding {
padding: 16px;
}
</style>