Merge branch 'master' of http://47.99.164.66:3000/hzdyjs-xg/all-project
This commit is contained in:
commit
94fdca480f
8 files changed
+1019
-59
No files matched your search
@@ -84,19 +84,28 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['stgl:activity:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && !['2', '3', '4', '5'].includes(selectedActivity.activityStatus)">
|
||||
<el-button icon="Edit" @click="handleUpdate()" v-hasPermi="['stgl:activity:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && ['0', '7', '6'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button icon="Edit" @click="handleUpdate()" v-hasPermi="['stgl:activity:edit']">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '0' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button type="success" icon="Upload" @click="handleSubmit()" v-hasPermi="['stgl:activity:edit']">提交</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && selectedActivity.activityStatus === '2' && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button type="warning" icon="Check" @click="handleApprove()" v-hasPermi="['stgl:activity:approve']">审批</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="!single && selectedActivity && ['3', '4'].includes(selectedActivity.activityStatus) && hasActivityOperationPermission(selectedActivity)">
|
||||
<el-button type="danger" icon="Close" @click="handleCancel()" v-hasPermi="['stgl:activity:edit']">取消活动</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button icon="CopyDocument" :disabled="single" @click="handleCopy()" v-hasPermi="['stgl:activity:add']">复制</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
icon="Delete"
|
||||
:disabled="multiple || (selectedActivity && selectedActivity.activityStatus !== '1')"
|
||||
:disabled="multiple || !['0', '7'].includes(selectedActivity?.activityStatus || '')"
|
||||
@click="handleDelete()"
|
||||
v-hasPermi="['stgl:activity:remove']"
|
||||
:title="selectedActivity && selectedActivity.activityStatus !== '1' ? '只有筹备中的活动可以删除' : ''"
|
||||
:title="selectedActivity && !['0', '7'].includes(selectedActivity.activityStatus) ? '只有草稿和已驳回状态的活动可以删除' : ''"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
@@ -195,7 +204,7 @@
|
||||
v-hasPermi="['stgl:activity:query']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="修改" placement="top" v-if="!['2', '3', '4', '5'].includes(scope.row.activityStatus)">
|
||||
<el-tooltip content="修改" placement="top" v-if="['0', '7', '6'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@@ -206,6 +215,39 @@
|
||||
v-hasPermi="['stgl:activity:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="提交" placement="top" v-if="scope.row.activityStatus === '0' && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="success"
|
||||
icon="Upload"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px"
|
||||
@click="handleSubmit(scope.row)"
|
||||
v-hasPermi="['stgl:activity:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="审批" placement="top" v-if="scope.row.activityStatus === '2' && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
icon="Check"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px"
|
||||
@click="handleApprove(scope.row)"
|
||||
v-hasPermi="['stgl:activity:approve']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="取消活动" placement="top" v-if="['3', '4'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
icon="Close"
|
||||
size="default"
|
||||
style="font-size: 16px; margin-right: 8px"
|
||||
@click="handleCancel(scope.row)"
|
||||
v-hasPermi="['stgl:activity:edit']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="复制" placement="top">
|
||||
<el-button
|
||||
link
|
||||
@@ -217,7 +259,7 @@
|
||||
v-hasPermi="['stgl:activity:add']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="活动总结" placement="top" v-if="shouldShowSummaryButton(scope.row)">
|
||||
<el-tooltip content="活动总结" placement="top" v-if="shouldShowSummaryButton(scope.row) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="success"
|
||||
@@ -239,7 +281,7 @@
|
||||
v-hasPermi="['stgl:activity:query']"
|
||||
></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top" v-if="scope.row.activityStatus === '1'">
|
||||
<el-tooltip content="删除" placement="top" v-if="['0', '7'].includes(scope.row.activityStatus) && hasActivityOperationPermission(scope.row)">
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@@ -315,16 +357,9 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="活动状态" prop="activityStatus">
|
||||
<el-select v-model="form.activityStatus" placeholder="请选择活动状态" style="width: 100%">
|
||||
<el-option v-for="dict in stgl_activity_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="关联社团" prop="relatedClubId">
|
||||
<ClubSelector v-model="form.relatedClub" @change="handleRelatedClubChange" />
|
||||
<ClubSelector v-model="form.relatedClub" @change="handleRelatedClubChange" :disabled="isRelatedClubDisabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -519,6 +554,37 @@
|
||||
:activity-name="selectedActivity?.activityName"
|
||||
ref="membersDialogRef"
|
||||
/>
|
||||
|
||||
<!-- 审批对话框 -->
|
||||
<el-dialog v-model="approveDialog.visible" title="审批活动" width="500px" append-to-body>
|
||||
<el-form ref="approveFormRef" :model="approveForm" label-width="100px">
|
||||
<el-form-item label="活动名称">
|
||||
<el-input v-model="approveForm.activityName" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="审批结果" prop="approvalResult">
|
||||
<el-radio-group v-model="approveForm.approvalResult">
|
||||
<el-radio label="approve">通过</el-radio>
|
||||
<el-radio label="reject">驳回</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="驳回原因" prop="rejectReason" v-if="approveForm.approvalResult === 'reject'">
|
||||
<el-input
|
||||
v-model="approveForm.rejectReason"
|
||||
type="textarea"
|
||||
placeholder="请输入驳回原因"
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="approveDialog.visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmApprove" :loading="approveLoading">确认审批</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -545,10 +611,12 @@ import ActivityDetailView from './components/ActivityDetailView.vue';
|
||||
import ActivityMembersDialog from './components/ActivityMembersDialog.vue';
|
||||
import ActivityRegistrationView from './components/ActivityRegistrationView.vue'; // Added import
|
||||
import { AdvisorVO } from '@/components/AdvisorManager/index.vue';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const { stgl_activity_type, stgl_activity_status, stgl_registration_type, stgl_registration_status, sys_yes_no } = toRefs<any>(
|
||||
proxy?.useDict('stgl_activity_type', 'stgl_activity_status', 'stgl_registration_type', 'stgl_registration_status', 'sys_yes_no')
|
||||
);
|
||||
@@ -570,6 +638,7 @@ const queryFormRef = ref<ElFormInstance>();
|
||||
const activityFormRef = ref<ElFormInstance>();
|
||||
const copyFormRef = ref<ElFormInstance>();
|
||||
const summaryFormRef = ref<ElFormInstance>();
|
||||
const approveFormRef = ref<ElFormInstance>();
|
||||
const membersDialogRef = ref();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
@@ -597,8 +666,26 @@ const membersDialog = reactive<DialogOption>({
|
||||
title: ''
|
||||
});
|
||||
|
||||
// 审批对话框
|
||||
const approveDialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
// 审批表单
|
||||
const approveForm = reactive({
|
||||
id: undefined as string | number | undefined,
|
||||
activityName: '',
|
||||
approvalResult: 'approve' as 'approve' | 'reject',
|
||||
rejectReason: ''
|
||||
});
|
||||
|
||||
const copyLoading = ref(false);
|
||||
const summaryLoading = ref(false);
|
||||
const approveLoading = ref(false);
|
||||
|
||||
// 关联社团禁用状态控制
|
||||
const isRelatedClubDisabled = ref(false);
|
||||
|
||||
const initFormData: StglActivityForm = {
|
||||
id: undefined,
|
||||
@@ -631,7 +718,7 @@ const initFormData: StglActivityForm = {
|
||||
teamSizeMin: undefined,
|
||||
teamSizeMax: undefined,
|
||||
needApproval: 1,
|
||||
activityStatus: '1',
|
||||
activityStatus: '0',
|
||||
isFinished: 0,
|
||||
summary: undefined,
|
||||
achievements: undefined,
|
||||
@@ -668,8 +755,7 @@ const data = reactive<PageData<StglActivityForm, StglActivityQuery & { relatedCl
|
||||
activityType: [{ required: true, message: '活动类型不能为空', trigger: 'change' }],
|
||||
startTime: [{ required: true, message: '开始时间不能为空', trigger: 'blur' }],
|
||||
endTime: [{ required: true, message: '结束时间不能为空', trigger: 'blur' }],
|
||||
organizerName: [{ required: true, message: '主办方名称不能为空', trigger: 'blur' }],
|
||||
activityStatus: [{ required: true, message: '活动状态不能为空', trigger: 'change' }]
|
||||
organizerName: [{ required: true, message: '主办方名称不能为空', trigger: 'blur' }]
|
||||
}
|
||||
});
|
||||
|
||||
@@ -753,6 +839,11 @@ const getList = async () => {
|
||||
queryParams.value.endTime = undefined;
|
||||
}
|
||||
|
||||
// 如果用户是社长角色,只能查看自己创建的活动
|
||||
if (proxy?.$auth.hasRole('stgl_president')) {
|
||||
queryParams.value.createBy = userStore.userId;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await listStglActivity(queryParams.value);
|
||||
activityList.value = res.rows;
|
||||
@@ -781,6 +872,15 @@ const reset = () => {
|
||||
form.value.instructorList = [];
|
||||
form.value.instructors = undefined;
|
||||
|
||||
// 重置关联社团禁用状态
|
||||
isRelatedClubDisabled.value = false;
|
||||
|
||||
// 重置审批表单
|
||||
approveForm.id = undefined;
|
||||
approveForm.activityName = '';
|
||||
approveForm.approvalResult = 'approve';
|
||||
approveForm.rejectReason = '';
|
||||
|
||||
// 更新formKey以强制重新渲染组件
|
||||
formKey.value++;
|
||||
|
||||
@@ -839,6 +939,9 @@ const handleAdd = () => {
|
||||
form.value.relatedClubId = queryParams.value.relatedClub.relatedClubId;
|
||||
form.value.relatedType = queryParams.value.relatedClub.relatedType;
|
||||
|
||||
// 设置关联社团字段为禁用状态(不允许修改)
|
||||
isRelatedClubDisabled.value = true;
|
||||
|
||||
console.log('新增活动 - 自动填充关联组织信息:', {
|
||||
relatedType: queryParams.value.relatedClub.relatedType,
|
||||
relatedClubId: queryParams.value.relatedClub.relatedClubId,
|
||||
@@ -851,6 +954,9 @@ const handleAdd = () => {
|
||||
formRelatedClubId: form.value.relatedClubId,
|
||||
formRelatedType: form.value.relatedType
|
||||
});
|
||||
} else {
|
||||
// 没有关联组织时,允许编辑关联社团字段
|
||||
isRelatedClubDisabled.value = false;
|
||||
}
|
||||
|
||||
dialog.visible = true;
|
||||
@@ -874,8 +980,8 @@ const handleUpdate = async (row?: StglActivityVO) => {
|
||||
// 先获取活动数据检查状态
|
||||
const res = await getStglActivity(_id);
|
||||
|
||||
// 检查活动状态是否允许修改(2:报名中、3:报名结束、4:进行中、5:已结束 不允许修改)
|
||||
if (['2', '3', '4', '5'].includes(res.data.activityStatus)) {
|
||||
// 检查活动状态是否允许修改(只有草稿0、已驳回7、已取消6状态允许修改)
|
||||
if (!['0', '7', '6'].includes(res.data.activityStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === res.data.activityStatus);
|
||||
const statusName = statusDict ? statusDict.label : '当前状态';
|
||||
proxy?.$modal.msgWarning(`活动状态为"${statusName}",不允许修改`);
|
||||
@@ -896,6 +1002,15 @@ const handleUpdate = async (row?: StglActivityVO) => {
|
||||
relatedType: res.data.relatedType,
|
||||
uniqueKey: `${res.data.relatedType}-${res.data.relatedClubId}`
|
||||
};
|
||||
|
||||
// 修改时,如果是从URL参数进入的,则禁用关联社团字段
|
||||
if (queryParams.value.relatedClub && queryParams.value.relatedClub.relatedClubId === res.data.relatedClubId) {
|
||||
isRelatedClubDisabled.value = true;
|
||||
} else {
|
||||
isRelatedClubDisabled.value = false;
|
||||
}
|
||||
} else {
|
||||
isRelatedClubDisabled.value = false;
|
||||
}
|
||||
|
||||
// 处理承办方数据
|
||||
@@ -945,6 +1060,11 @@ const submitForm = () => {
|
||||
// 准备提交的数据
|
||||
const submitData = { ...form.value } as any;
|
||||
|
||||
// 新增时自动设置活动状态为0(草稿)
|
||||
if (!submitData.id) {
|
||||
submitData.activityStatus = '0';
|
||||
}
|
||||
|
||||
// 处理关联社团数据
|
||||
if (submitData.relatedClub) {
|
||||
submitData.relatedClubId = submitData.relatedClub.relatedClubId;
|
||||
@@ -1032,23 +1152,23 @@ const handleDelete = async (row?: StglActivityVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
let confirmMessage = '';
|
||||
|
||||
// 检查删除权限 - 只有筹备中(状态1)的活动可以删除
|
||||
// 检查删除权限 - 只有草稿(状态0)和已驳回(状态7)的活动可以删除
|
||||
if (row) {
|
||||
if (row.activityStatus !== '1') {
|
||||
if (!['0', '7'].includes(row.activityStatus)) {
|
||||
const statusDict = stgl_activity_status.value.find((dict: any) => dict.value === row.activityStatus);
|
||||
const statusName = statusDict ? statusDict.label : '当前状态';
|
||||
proxy?.$modal.msgWarning(`活动状态为"${statusName}",只有筹备中的活动可以删除`);
|
||||
proxy?.$modal.msgWarning(`活动状态为"${statusName}",只有草稿和已驳回状态的活动可以删除`);
|
||||
return;
|
||||
}
|
||||
confirmMessage = `是否确认删除活动"${row.activityName}"?`;
|
||||
} else {
|
||||
const selectedItems = activityList.value.filter((item) => ids.value.includes(item.id));
|
||||
|
||||
// 检查选中的活动是否都是筹备中状态
|
||||
const nonDeletableItems = selectedItems.filter((item) => item.activityStatus !== '1');
|
||||
// 检查选中的活动是否都是草稿或已驳回状态
|
||||
const nonDeletableItems = selectedItems.filter((item) => !['0', '7'].includes(item.activityStatus));
|
||||
if (nonDeletableItems.length > 0) {
|
||||
const names = nonDeletableItems.map((item) => item.activityName).join('、');
|
||||
proxy?.$modal.msgWarning(`活动"${names}"不是筹备中状态,只有筹备中的活动可以删除`);
|
||||
proxy?.$modal.msgWarning(`活动"${names}"不是草稿或已驳回状态,只有草稿和已驳回状态的活动可以删除`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1273,6 +1393,127 @@ const handleMembersReview = (row: StglActivityVO) => {
|
||||
membersDialog.title = `${row.activityName}活动报名管理`;
|
||||
};
|
||||
|
||||
/** 提交按钮操作 */
|
||||
const handleSubmit = async (row?: StglActivityVO) => {
|
||||
const activity = row || selectedActivity.value;
|
||||
if (!activity) return;
|
||||
|
||||
try {
|
||||
await proxy?.$modal.confirm(`是否确认提交活动"${activity.activityName}"?提交后将进入审批流程。`);
|
||||
|
||||
// 调用后端接口更新活动状态为2(待审批)
|
||||
// 传递完整的活动数据,避免后端验证失败
|
||||
await updateStglActivity({
|
||||
...activity,
|
||||
activityStatus: '2'
|
||||
});
|
||||
|
||||
proxy?.$modal.msgSuccess('提交成功');
|
||||
await getList();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('提交失败:', error);
|
||||
proxy?.$modal.msgError('提交失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 审批按钮操作 */
|
||||
const handleApprove = async (row?: StglActivityVO) => {
|
||||
const activity = row || selectedActivity.value;
|
||||
if (!activity) return;
|
||||
|
||||
// 显示审批对话框
|
||||
approveDialog.visible = true;
|
||||
approveDialog.title = `审批活动 - ${activity.activityName}`;
|
||||
approveForm.id = activity.id;
|
||||
approveForm.activityName = activity.activityName || '';
|
||||
approveForm.approvalResult = 'approve';
|
||||
approveForm.rejectReason = '';
|
||||
};
|
||||
|
||||
/** 取消活动按钮操作 */
|
||||
const handleCancel = async (row?: StglActivityVO) => {
|
||||
const activity = row || selectedActivity.value;
|
||||
if (!activity) return;
|
||||
|
||||
try {
|
||||
await proxy?.$modal.confirm(`是否确认取消活动"${activity.activityName}"?取消后将无法恢复。`);
|
||||
|
||||
// 调用后端接口更新活动状态为6(已取消)
|
||||
// 传递完整的活动数据,避免后端验证失败
|
||||
await updateStglActivity({
|
||||
...activity,
|
||||
activityStatus: '6'
|
||||
});
|
||||
|
||||
proxy?.$modal.msgSuccess('取消活动成功');
|
||||
await getList();
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('取消活动失败:', error);
|
||||
proxy?.$modal.msgError('取消活动失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 确认审批 */
|
||||
const confirmApprove = async () => {
|
||||
if (!approveFormRef.value) return;
|
||||
|
||||
approveLoading.value = true;
|
||||
try {
|
||||
const activity = activityList.value.find(item => item.id === approveForm.id);
|
||||
if (!activity) {
|
||||
proxy?.$modal.msgError('活动信息不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
let newStatus: string;
|
||||
let successMessage: string;
|
||||
|
||||
if (approveForm.approvalResult === 'approve') {
|
||||
// 审批通过,根据时间比较确定状态
|
||||
const now = new Date();
|
||||
const startTime = new Date(activity.startTime);
|
||||
const endTime = new Date(activity.endTime);
|
||||
|
||||
if (now < startTime) {
|
||||
newStatus = '1'; // 未开始
|
||||
} else if (now >= startTime && now <= endTime) {
|
||||
newStatus = '4'; // 进行中
|
||||
} else {
|
||||
newStatus = '5'; // 已结束
|
||||
}
|
||||
successMessage = '审批通过';
|
||||
} else {
|
||||
// 审批驳回
|
||||
if (!approveForm.rejectReason.trim()) {
|
||||
proxy?.$modal.msgWarning('请输入驳回原因');
|
||||
return;
|
||||
}
|
||||
newStatus = '7'; // 已驳回
|
||||
successMessage = '审批驳回';
|
||||
}
|
||||
|
||||
// 调用后端接口更新活动状态
|
||||
// 传递完整的活动数据,避免后端验证失败
|
||||
await updateStglActivity({
|
||||
...activity,
|
||||
activityStatus: newStatus
|
||||
});
|
||||
|
||||
proxy?.$modal.msgSuccess(successMessage);
|
||||
approveDialog.visible = false;
|
||||
await getList();
|
||||
} catch (error) {
|
||||
console.error('审批失败:', error);
|
||||
proxy?.$modal.msgError('审批失败');
|
||||
} finally {
|
||||
approveLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 格式化日期 */
|
||||
const formatDate = (dateStr: string): string => {
|
||||
if (!dateStr) return '';
|
||||
@@ -1303,6 +1544,51 @@ const getAdvisorNames = (activity: StglActivityVO): string[] => {
|
||||
return [];
|
||||
};
|
||||
|
||||
// 检查是否拥有指导老师或管理员权限
|
||||
const hasInstructorPermission = computed(() => {
|
||||
return proxy?.$auth.hasRoleOr(['stgl_instructor', 'stgl_stgl_admin', 'superadmin']);
|
||||
});
|
||||
|
||||
// 检查当前用户是否为指定活动的指导老师
|
||||
const isCurrentUserAdvisor = (activity: StglActivityVO): boolean => {
|
||||
if (!activity.instructors) return false;
|
||||
|
||||
try {
|
||||
const advisors = JSON.parse(activity.instructors);
|
||||
if (Array.isArray(advisors)) {
|
||||
return advisors.some((advisor: any) => {
|
||||
// 支持两种数据结构:直接包含userId或嵌套在teacher对象中
|
||||
const userId = advisor.userId || advisor.teacher?.userId;
|
||||
return userId && userId.toString() === userStore.userId?.toString();
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('解析活动指导老师数据失败:', error);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// 检查当前用户是否有活动操作权限(指导老师只能操作自己指导的活动)
|
||||
const hasActivityOperationPermission = (activity: StglActivityVO): boolean => {
|
||||
// 管理员有所有权限
|
||||
if (proxy?.$auth.hasRole('admin') || proxy?.$auth.hasRole('common')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 指导老师只能操作自己指导的活动
|
||||
if (proxy?.$auth.hasRole('stgl_instructor')) {
|
||||
return isCurrentUserAdvisor(activity);
|
||||
}
|
||||
|
||||
// 社长只能操作自己创建的活动
|
||||
if (proxy?.$auth.hasRole('stgl_president')) {
|
||||
return activity.createBy === userStore.userId;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initUrlParams();
|
||||
getList();
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
|
||||
<el-row>
|
||||
<el-col :span="24" class="search-btn-container">
|
||||
<el-form-item>
|
||||
@@ -619,6 +621,18 @@
|
||||
</template>
|
||||
|
||||
<script setup name="StglClub" lang="ts">
|
||||
/**
|
||||
* 社团信息管理
|
||||
*
|
||||
* 权限控制说明:
|
||||
* - stgl_president角色:可以操作自己担任社长的社团(无论是否为创建者)
|
||||
* - stgl_instructor角色:指导老师,有部分字段的只读权限
|
||||
* - 管理员角色:可以操作所有社团
|
||||
*
|
||||
* 业务逻辑:
|
||||
* 管理员创建社团后选择社长,被选中的社长(stgl_president角色)
|
||||
* 需要能够看到和操作自己担任社长的社团,不再受限于创建者身份
|
||||
*/
|
||||
import { useRouter } from 'vue-router';
|
||||
import {
|
||||
listStglClub,
|
||||
@@ -646,9 +660,15 @@ const { stgl_club_type, sys_normal_disable, stgl_funding_source, sys_yes_no } =
|
||||
|
||||
// 检查是否拥有指导老师或管理员权限
|
||||
const hasInstructorPermission = computed(() => {
|
||||
return proxy?.$auth.hasRoleOr(['stgl_instructor', 'stgl_admin', 'superadmin']);
|
||||
return proxy?.$auth.hasRoleOr(['stgl_instructor', 'stgl_stgl_admin', 'superadmin']);
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 社长权限控制 - 检查用户是否为各社团的社长(无论是否为创建者)
|
||||
// 用于控制转让按钮显示和社长相关操作权限
|
||||
const presidentRoles = ref<Record<string | number, boolean>>({});
|
||||
|
||||
const clubList = ref<StglClubVO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
@@ -660,9 +680,6 @@ const total = ref(0);
|
||||
const activeTab = ref('basic');
|
||||
const charterDownloading = ref(false);
|
||||
|
||||
// 社长权限控制
|
||||
const presidentRoles = ref<Record<string | number, boolean>>({});
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const clubFormRef = ref<ElFormInstance>();
|
||||
|
||||
@@ -1281,7 +1298,7 @@ const handleAdvisorsChange = (advisors: AdvisorVO[]) => {
|
||||
});
|
||||
};
|
||||
|
||||
/** 检查用户是否为指定社团的社长 */
|
||||
/** 检查用户是否为指定社团的社长(无论是否为创建者) */
|
||||
const checkIsPresident = async (clubId: string | number): Promise<boolean> => {
|
||||
try {
|
||||
console.log('🔍 checkIsPresident: 开始检查社长权限, clubId:', clubId);
|
||||
@@ -1296,7 +1313,7 @@ const checkIsPresident = async (clubId: string | number): Promise<boolean> => {
|
||||
}
|
||||
};
|
||||
|
||||
/** 批量检查社长权限 */
|
||||
/** 批量检查社长权限(检查用户是否为各社团的社长,无论是否为创建者) */
|
||||
const checkBatchPresidentRoles = async (clubs: StglClubVO[]) => {
|
||||
console.log('🔍 checkBatchPresidentRoles: 开始批量检查权限, clubs数量:', clubs.length);
|
||||
const checks = clubs.map(async (club) => {
|
||||
@@ -1334,7 +1351,7 @@ const shouldShowTransferButton = (club: StglClubVO): boolean => {
|
||||
console.log('⏳ shouldShowTransferButton: 权限检查未完成,返回false避免闪现');
|
||||
return false;
|
||||
}
|
||||
// 只有社长才能看到转让按钮
|
||||
// 社长可以看到转让按钮(无论是否为创建者)
|
||||
const result = isPresident === true;
|
||||
console.log('🔍 shouldShowTransferButton: stgl_president角色最终结果:', result);
|
||||
return result;
|
||||
@@ -1689,6 +1706,8 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 人员信息部分样式 */
|
||||
.personnel-section {
|
||||
margin-bottom: 24px;
|
||||
|
||||
Reference in new issue
Block a user