课程强制发布
This commit is contained in:
@@ -176,6 +176,16 @@ export const courseApi = {
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 强制发布课程(跳过敏感词校验)
|
||||
* @param courseID 课程ID
|
||||
* @returns Promise<ResultDomain<Course>>
|
||||
*/
|
||||
async forcePublishCourse(courseID: string): Promise<ResultDomain<Course>> {
|
||||
const response = await api.post<Course>(`${this.prefixCourse}/${courseID}/force-publish`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取课程章节列表
|
||||
* @param courseID 课程ID
|
||||
|
||||
@@ -6,7 +6,7 @@ import App from "./App.vue";
|
||||
import "./registerServiceWorker";
|
||||
import router from "./router";
|
||||
import store from "./store";
|
||||
import { setupRouterGuards, setupTokenRefresh } from "@/utils/permission";
|
||||
import { setupRouterGuards, setupTokenRefresh, setupPermissionUtils } from "@/utils/permission";
|
||||
import { setupPermissionDirectives } from "@/directives/permission";
|
||||
|
||||
// 引入 Quill 富文本编辑器样式(全局)
|
||||
@@ -49,6 +49,9 @@ async function initApp() {
|
||||
// 设置权限指令
|
||||
setupPermissionDirectives(app, store);
|
||||
|
||||
// 设置权限工具
|
||||
setupPermissionUtils(store);
|
||||
|
||||
// 设置路由守卫
|
||||
setupRouterGuards(router, store);
|
||||
|
||||
|
||||
@@ -266,3 +266,64 @@ export class PermissionChecker {
|
||||
return roleCodes.some(code => this.hasRole(code));
|
||||
}
|
||||
}
|
||||
|
||||
// 全局store引用,由setupPermissionUtils初始化
|
||||
let globalStore: Store<any> | null = null;
|
||||
|
||||
/**
|
||||
* 初始化权限工具(在main.ts中调用)
|
||||
*/
|
||||
export function setupPermissionUtils(store: Store<any>) {
|
||||
globalStore = store;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限检查 Composition API(用于Vue组件)
|
||||
*/
|
||||
export function usePermission() {
|
||||
return {
|
||||
/**
|
||||
* 检查是否有指定权限
|
||||
*/
|
||||
hasPermission: (permissionCode: string): boolean => {
|
||||
if (!globalStore) return false;
|
||||
return globalStore.getters['auth/hasPermission'](permissionCode);
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否有任意一个权限
|
||||
*/
|
||||
hasAnyPermission: (permissionCodes: string[]): boolean => {
|
||||
if (!globalStore) return false;
|
||||
return globalStore.getters['auth/hasAnyPermission'](permissionCodes);
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否有所有权限
|
||||
*/
|
||||
hasAllPermissions: (permissionCodes: string[]): boolean => {
|
||||
if (!globalStore) return false;
|
||||
return globalStore.getters['auth/hasAllPermissions'](permissionCodes);
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否有指定角色
|
||||
*/
|
||||
hasRole: (roleCode: string): boolean => {
|
||||
if (!globalStore) return false;
|
||||
const userRoles = globalStore.getters['auth/userRoles'] || [];
|
||||
return userRoles.some((role: any) => role.code === roleCode);
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查是否有任意一个角色
|
||||
*/
|
||||
hasAnyRole: (roleCodes: string[]): boolean => {
|
||||
if (!globalStore) return false;
|
||||
const userRoles = globalStore.getters['auth/userRoles'] || [];
|
||||
return roleCodes.some(code =>
|
||||
userRoles.some((role: any) => role.code === code)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
{{ getActionButtonText(row.status) }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === ResourceStatus.SENSITIVE_FAILED"
|
||||
v-if="row.status === ResourceStatus.SENSITIVE_FAILED && canForcePublish"
|
||||
size="small"
|
||||
type="warning"
|
||||
@click="forcePublishArticle(row)"
|
||||
@@ -108,7 +108,7 @@ import { AdminLayout } from '@/views/admin';
|
||||
defineOptions({
|
||||
name: 'ArticleManagementView'
|
||||
});
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { ElButton, ElInput, ElTable, ElTableColumn, ElTag, ElPagination, ElMessage, ElMessageBox, ElIcon } from 'element-plus';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -116,8 +116,14 @@ import { resourceApi, resourceTagApi } from '@/apis/resource'
|
||||
import type { PageParam, ResourceSearchParams, Resource, Tag } from '@/types';
|
||||
import { ArticleShowView } from '@/views/public/article';
|
||||
import { ResourceStatus } from '@/types/enums';
|
||||
import { usePermission } from '@/utils/permission';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 权限检查
|
||||
const { hasPermission } = usePermission();
|
||||
const canForcePublish = computed(() => hasPermission('admin:article:force-publish'));
|
||||
|
||||
const searchKeyword = ref('');
|
||||
const pageParam = ref<PageParam>({
|
||||
pageNumber: 1,
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="80" />
|
||||
<el-table-column label="操作" width="250" fixed="right">
|
||||
<el-table-column label="操作" width="300" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" size="small" link @click="handleEdit(row)">
|
||||
编辑
|
||||
@@ -87,6 +87,15 @@
|
||||
>
|
||||
发布
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 4 && canForcePublish"
|
||||
type="warning"
|
||||
size="small"
|
||||
link
|
||||
@click="handleForcePublish(row)"
|
||||
>
|
||||
强制发布
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 1"
|
||||
type="warning"
|
||||
@@ -121,12 +130,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { Search, Plus } from '@element-plus/icons-vue';
|
||||
import { courseApi } from '@/apis/study';
|
||||
import { FILE_DOWNLOAD_URL } from '@/config';
|
||||
import type { Course } from '@/types';
|
||||
import { usePermission } from '@/utils/permission';
|
||||
|
||||
defineOptions({
|
||||
name: 'CourseList'
|
||||
@@ -137,6 +147,10 @@ const emit = defineEmits<{
|
||||
edit: [course: Course];
|
||||
}>();
|
||||
|
||||
// 权限检查
|
||||
const { hasPermission } = usePermission();
|
||||
const canForcePublish = computed(() => hasPermission('admin:course:force-publish'));
|
||||
|
||||
const loading = ref(false);
|
||||
const courseList = ref<Course[]>([]);
|
||||
const total = ref(0);
|
||||
@@ -211,7 +225,7 @@ async function handleUpdateStatus(course: Course, status: number) {
|
||||
ElMessage.success(`${statusText}成功`);
|
||||
loadCourses();
|
||||
} else {
|
||||
ElMessage.error(`${statusText}失败`);
|
||||
ElMessage.error(res.message || `${statusText}失败`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
@@ -221,6 +235,33 @@ async function handleUpdateStatus(course: Course, status: number) {
|
||||
}
|
||||
}
|
||||
|
||||
// 强制发布
|
||||
async function handleForcePublish(course: Course) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要强制发布课程「${course.name}」吗?此操作将跳过敏感词校验。`,
|
||||
'强制发布确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
);
|
||||
const res = await courseApi.forcePublishCourse(course.courseID!);
|
||||
if (res.success) {
|
||||
ElMessage.success('强制发布成功');
|
||||
loadCourses();
|
||||
} else {
|
||||
ElMessage.error(res.message || '强制发布失败');
|
||||
}
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('强制发布失败:', error);
|
||||
ElMessage.error('强制发布失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除
|
||||
async function handleDelete(course: Course) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user