|
|
@@ -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();
|