update:项目管理&赛事管理
This commit is contained in:
parent
68127a81fa
commit
fe000094c3
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
|
||||
@ -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' }],
|
||||
|
||||
@ -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(`验证失败,请检查输入`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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">
|
||||
|
||||
222
src/views/match/points/config/index.vue
Normal file
222
src/views/match/points/config/index.vue
Normal 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>
|
||||
138
src/views/match/points/general/index.vue
Normal file
138
src/views/match/points/general/index.vue
Normal 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>
|
||||
@ -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 },
|
||||
]);
|
||||
|
||||
135
src/views/match/points/unit/index.vue
Normal file
135
src/views/match/points/unit/index.vue
Normal 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>
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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>
|
||||
Loading…
x
Reference in New Issue
Block a user