修复分类问题
This commit is contained in:
+12
-7
@@ -100,22 +100,27 @@ export function getFileById(id) {
|
|||||||
* 上传文件
|
* 上传文件
|
||||||
* @param {FormData} formData 文件数据
|
* @param {FormData} formData 文件数据
|
||||||
* @param {Object} options 额外选项
|
* @param {Object} options 额外选项
|
||||||
* @param {string} [options.cate]
|
* @param {string|number} [options.cate] 文件分组ID,0 为未分类
|
||||||
|
* @param {(e: { loaded: number; total?: number }) => void} [options.onUploadProgress] 上传进度
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
export function uploadFile(formData, options = {}) {
|
export function uploadFile(formData, options = {}) {
|
||||||
if (options.cate) {
|
// 0 表示「未分类」,不能用 truthy 判断
|
||||||
formData.append('cate', options.cate);
|
if (options.cate !== undefined && options.cate !== null && options.cate !== "") {
|
||||||
|
formData.append("cate", String(options.cate));
|
||||||
}
|
}
|
||||||
|
|
||||||
return request({
|
const config = {
|
||||||
url: "/backend/uploadfile",
|
url: "/backend/uploadfile",
|
||||||
method: "post",
|
method: "post",
|
||||||
data: formData,
|
data: formData,
|
||||||
headers: {
|
// 上传大文件不设超时;勿手写 Content-Type(需浏览器生成 multipart boundary)
|
||||||
"Content-Type": "multipart/form-data"
|
timeout: 0,
|
||||||
|
};
|
||||||
|
if (typeof options.onUploadProgress === "function") {
|
||||||
|
config.onUploadProgress = options.onUploadProgress;
|
||||||
}
|
}
|
||||||
});
|
return request(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import axios from 'axios';
|
|||||||
// 获取API基础URL,添加调试信息
|
// 获取API基础URL,添加调试信息
|
||||||
const apiBaseURL = import.meta.env.VITE_API_BASE_URL;
|
const apiBaseURL = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例(普通接口 5min;大文件上传在 api/file.js 单独设置更长 timeout)
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: apiBaseURL,
|
baseURL: apiBaseURL,
|
||||||
timeout: 10000,
|
timeout: 300000,
|
||||||
withCredentials: false // JWT 不需要 Cookie
|
withCredentials: false // JWT 不需要 Cookie
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -18,9 +18,13 @@ service.interceptors.request.use(
|
|||||||
config.headers['Authorization'] = `Bearer ${token}`;
|
config.headers['Authorization'] = `Bearer ${token}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对于有 body 的请求(POST、PUT、PATCH),确保设置 Content-Type
|
// 对于有 body 的请求(POST、PUT、PATCH),默认 JSON;
|
||||||
|
// FormData 必须由浏览器自行设置 Content-Type,否则缺少 multipart boundary,服务端无法解析
|
||||||
if (config.data && ['post', 'put', 'patch'].includes(config.method?.toLowerCase())) {
|
if (config.data && ['post', 'put', 'patch'].includes(config.method?.toLowerCase())) {
|
||||||
if (!config.headers['Content-Type'] && !config.headers['content-type']) {
|
if (typeof FormData !== 'undefined' && config.data instanceof FormData) {
|
||||||
|
delete config.headers['Content-Type'];
|
||||||
|
delete config.headers['content-type'];
|
||||||
|
} else if (!config.headers['Content-Type'] && !config.headers['content-type']) {
|
||||||
config.headers['Content-Type'] = 'application/json';
|
config.headers['Content-Type'] = 'application/json';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +58,11 @@ service.interceptors.response.use(
|
|||||||
console.error('请求失败,请稍后再试');
|
console.error('请求失败,请稍后再试');
|
||||||
}
|
}
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
|
if (error.code === 'ECONNABORTED') {
|
||||||
|
console.error('请求超时,请稍后重试');
|
||||||
|
} else {
|
||||||
console.error('请求失败,请检查网络连接');
|
console.error('请求失败,请检查网络连接');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('请求配置错误');
|
console.error('请求配置错误');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,14 +47,19 @@
|
|||||||
|
|
||||||
<div class="category-actions">
|
<div class="category-actions">
|
||||||
<el-button-group size="small">
|
<el-button-group size="small">
|
||||||
<el-button type="text" title="编辑" @click.stop="$emit('edit', item)">
|
<el-button
|
||||||
|
v-if="!isGlobal"
|
||||||
|
type="text"
|
||||||
|
title="编辑"
|
||||||
|
@click.stop="$emit('edit', item)"
|
||||||
|
>
|
||||||
<el-icon><Edit /></el-icon>
|
<el-icon><Edit /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="text" title="添加子分类" @click.stop="$emit('add-child', item)">
|
<el-button type="text" title="添加子分类" @click.stop="$emit('add-child', item)">
|
||||||
<el-icon><Plus /></el-icon>
|
<el-icon><Plus /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="item.tid !== 0"
|
v-if="!isGlobal"
|
||||||
type="text"
|
type="text"
|
||||||
class="danger"
|
class="danger"
|
||||||
title="删除"
|
title="删除"
|
||||||
@@ -62,7 +67,7 @@
|
|||||||
>
|
>
|
||||||
<el-icon><Delete /></el-icon>
|
<el-icon><Delete /></el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-tag v-else type="info" size="small" title="全局分类不可删除">
|
<el-tag v-if="isGlobal" type="info" size="small" title="全局分类不可修改或删除">
|
||||||
全局
|
全局
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</el-button-group>
|
</el-button-group>
|
||||||
@@ -88,6 +93,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { computed } from "vue";
|
||||||
import { ArrowDown, ArrowRight, Edit, Plus, Delete, Document } from "@element-plus/icons-vue";
|
import { ArrowDown, ArrowRight, Edit, Plus, Delete, Document } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -97,6 +103,11 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['edit', 'add-child', 'delete']);
|
const emit = defineEmits(['edit', 'add-child', 'delete']);
|
||||||
|
|
||||||
|
// 全局分类(tid = 0)由平台维护,租户端不能编辑或删除
|
||||||
|
const isGlobal = computed(
|
||||||
|
() => props.item.is_global === true || Number(props.item.tid) === 0
|
||||||
|
);
|
||||||
|
|
||||||
const toggleExpand = () => {
|
const toggleExpand = () => {
|
||||||
props.item.expanded = !props.item.expanded;
|
props.item.expanded = !props.item.expanded;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -245,9 +245,8 @@ async function handleSubmit() {
|
|||||||
if (fileList.value.length > 0 && fileList.value[0].raw) {
|
if (fileList.value.length > 0 && fileList.value[0].raw) {
|
||||||
const uploadFormData = new FormData()
|
const uploadFormData = new FormData()
|
||||||
uploadFormData.append('file', fileList.value[0].raw)
|
uploadFormData.append('file', fileList.value[0].raw)
|
||||||
uploadFormData.append('cate', 'category')
|
|
||||||
|
|
||||||
const uploadRes = await uploadFile(uploadFormData)
|
const uploadRes: any = await uploadFile(uploadFormData)
|
||||||
if (uploadRes?.data?.url) {
|
if (uploadRes?.data?.url) {
|
||||||
imageUrl = uploadRes.data.url
|
imageUrl = uploadRes.data.url
|
||||||
}
|
}
|
||||||
@@ -262,17 +261,20 @@ async function handleSubmit() {
|
|||||||
cid: formData.parentId,
|
cid: formData.parentId,
|
||||||
}
|
}
|
||||||
if (isEdit.value) {
|
if (isEdit.value) {
|
||||||
await editCategory(formData.id, payload)
|
const res: any = await editCategory(formData.id, payload)
|
||||||
|
if (res?.code && res.code !== 200) throw res
|
||||||
ElMessage.success('更新成功')
|
ElMessage.success('更新成功')
|
||||||
} else {
|
} else {
|
||||||
await createCategory(payload)
|
const res: any = await createCategory(payload)
|
||||||
|
if (res?.code && res.code !== 200) throw res
|
||||||
ElMessage.success('创建成功')
|
ElMessage.success('创建成功')
|
||||||
}
|
}
|
||||||
emit('saved')
|
emit('saved')
|
||||||
closeDialog()
|
closeDialog()
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
ElMessage.error(isEdit.value ? '更新失败' : '创建失败')
|
const msg = err?.response?.data?.msg || err?.msg
|
||||||
|
ElMessage.error(msg || (isEdit.value ? '更新失败' : '创建失败'))
|
||||||
} finally {
|
} finally {
|
||||||
submitLoading.value = false
|
submitLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,9 +70,8 @@ const searchText = ref("");
|
|||||||
const categories = ref([]);
|
const categories = ref([]);
|
||||||
|
|
||||||
// 新增分类
|
// 新增分类
|
||||||
const addCategory = ref(null);
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
addCategory.value = { parentId: 0 };
|
currentEdit.value = { parentId: 0 };
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,6 +127,10 @@ function handleCreate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleEdit(category) {
|
function handleEdit(category) {
|
||||||
|
if (Number(category.tid) === 0 || category.is_global === true) {
|
||||||
|
ElMessage.warning("全局分类不可修改");
|
||||||
|
return;
|
||||||
|
}
|
||||||
currentEdit.value = category;
|
currentEdit.value = category;
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user