feat):(course 实现课程创建功能及文件云组件

- 添加创建课程页面,支持章节与节的嵌套结构
- 实现可折叠章节组件(dragCollapse),支持展开/收起与删除操作
- 实现可拖拽表格组件(dragTable),支持跨表格拖拽排序与编辑
- 引入文件云API模块,支持文件夹与文件的基本操作
- 添加文件类型图标样式文件(filetypes.css)
- 新增文件选择弹窗组件(FileCloud),支持文件浏览与选择
- 优化common.scss样式文件,调整选择器缩进与渐变背景配置
This commit is contained in:
陈昱达
2025-11-19 15:46:20 +08:00
parent 2682f66111
commit 740ad58897
17 changed files with 2820 additions and 385 deletions

187
src/api/modules/xajax.js Normal file
View File

@@ -0,0 +1,187 @@
import axios from "axios";
import qs from "qs";
import { notification, Modal, message } from "ant-design-vue";
// 登录重定向 URL可根据环境变量配置
const ReLoginUrl = process.env.VUE_APP_LOGIN_URL || "/login";
const TokenName = "XBOE-Access-Token";
// JSON 请求实例Content-Type: application/json
const jsonRequest = axios.create({
headers: { "Content-Type": "application/json;charset=utf-8" },
// baseURL: process.env.VUE_APP_BASE_API,
timeout: 60000,
});
// 请求拦截器 - 不再携带 token你要求移除 getToken
jsonRequest.interceptors.request.use(
(config) => {
// ⚠️ 已移除 getToken 相关逻辑
// 如果后续需要手动加 token可在此处添加
// config.headers[TokenName] = 'your-token';
return config;
},
(error) => {
console.error("Request error:", error);
return Promise.reject(error);
}
);
// 响应拦截器
jsonRequest.interceptors.response.use(
(res) => {
const code = res.data.status || 200;
if (code === 200) {
return res.data;
} else {
if (code === 6001 || code === 401 || code === 402) {
Modal.warning({
title: "登录失效",
content: "您已被登出,可以取消继续留在该页面,或者重新登录",
okText: "重新登录",
onOk() {
window.location.href = ReLoginUrl;
},
});
} else if (code === 403) {
message.error("当前操作没有权限");
} else if (code === 302) {
window.location.href = ReLoginUrl;
} else {
// 其他业务错误,直接返回数据供调用方处理
return res.data; // 不 throw 错误,方便前端自定义处理
}
}
},
(error) => {
console.error("Response error:", error);
let msg = "未知错误,请稍后重试";
if (error.message === "Network Error") {
msg = "网络异常,请检查网络连接";
} else if (error.message.includes("timeout")) {
msg = "系统接口请求超时";
} else if (error.message.includes("Request failed with status code")) {
const statusCode = error.message.substr(-3);
msg = `系统接口 ${statusCode} 异常`;
if (statusCode === "500") {
notification.error({
message: "服务错误",
description: "服务器内部错误,请联系管理员。",
duration: 5,
});
}
}
message.error(msg, 5);
return Promise.reject(error);
}
);
// Form 请求实例x-www-form-urlencoded
const formRequest = axios.create({
headers: { "Content-Type": "application/x-www-form-urlencoded" },
// baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000,
});
// 请求拦截器form
formRequest.interceptors.request.use(
(config) => {
// 同样不带 token
return config;
},
(error) => {
console.error("Form request error:", error);
return Promise.reject(error);
}
);
// 响应拦截器form
formRequest.interceptors.response.use(
(res) => {
const code = res.data.status || 200;
if (code === 200) {
return res.data;
} else {
if (code === 6001 || code === 401 || code === 402) {
Modal.warning({
title: "登录已过期",
content: "登录状态无效,即将跳转至登录页",
okText: "确认",
onOk() {
window.location.href = ReLoginUrl;
},
});
} else if (code === 403) {
message.error("暂无权限执行此操作");
} else if (code === 302) {
window.location.href = ReLoginUrl;
} else {
return res.data; // 返回原始数据供业务判断
}
}
},
(error) => {
console.error("Form response error:", error);
let msg = "请求失败";
if (error.message === "Network Error") {
msg = "网络连接失败";
} else if (error.message.includes("timeout")) {
msg = "请求超时";
} else if (error.message.includes("Request failed with status code")) {
msg = `服务端异常 (${error.message.slice(-3)})`;
}
message.error(msg, 5);
return Promise.reject(error);
}
);
// ================== API 方法封装 ==================
const requestJson = jsonRequest.request;
const get = (url, params, config) => {
const finalConfig = { ...config, params };
return formRequest.get(url, finalConfig);
};
const post = (url, data, config) => {
return formRequest.post(url, qs.stringify(data), config);
};
const postForm = (url, data, config) => {
return formRequest.post(url, data, config); // 不 stringify用于上传文件等
};
const postJson = jsonRequest.post;
const put = (url, data, config) => {
return formRequest.put(url, qs.stringify(data), config);
};
const putJson = jsonRequest.put;
const patch = (url, data, config) => {
return formRequest.patch(url, qs.stringify(data), config);
};
const patchJson = jsonRequest.patch;
const del = (url, config) => {
return formRequest.delete(url, config);
};
// 导出统一接口
export default {
request: jsonRequest.request, // 通用 request 方法
requestJson,
get,
post,
postForm,
postJson,
put,
putJson,
patch,
patchJson,
del,
};