@liujitcn/kratos-admin-core 0.0.59 → 0.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -61,7 +61,8 @@ const props = withDefaults(defineProps<RichEditorProps>(), {
|
|
|
61
61
|
disabled: false,
|
|
62
62
|
uploadType: "content"
|
|
63
63
|
});
|
|
64
|
-
|
|
64
|
+
// 拷贝出独立的菜单配置,避免后续覆盖 uploadImage/uploadVideo 时直接修改父组件的 props.editorConfig.MENU_CONF。
|
|
65
|
+
const editorMenuConfig = { ...(props.editorConfig.MENU_CONF ?? {}) };
|
|
65
66
|
const resolvedEditorConfig = computed(() => ({
|
|
66
67
|
...props.editorConfig,
|
|
67
68
|
placeholder: props.editorConfig.placeholder || t("common.placeholder.input_content"),
|
|
@@ -78,7 +79,7 @@ const self_disabled = computed(() => {
|
|
|
78
79
|
});
|
|
79
80
|
|
|
80
81
|
// 判断当前富文本编辑器是否禁用
|
|
81
|
-
if (self_disabled.value) nextTick(() => editorRef.value
|
|
82
|
+
if (self_disabled.value) nextTick(() => editorRef.value?.disable());
|
|
82
83
|
|
|
83
84
|
// 富文本的内容监听,触发父组件改变,实现双向数据绑定
|
|
84
85
|
const emit = defineEmits<{
|
|
@@ -96,11 +97,57 @@ const valueHtml = computed({
|
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
99
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
/** 富文本图片上传允许的 MIME 类型。 */
|
|
101
|
+
const IMAGE_MIME_TYPES = ["image/jpeg", "image/png", "image/gif"];
|
|
102
|
+
/** 富文本图片上传大小上限(MB)。 */
|
|
103
|
+
const IMAGE_MAX_SIZE = 5;
|
|
104
|
+
/** 富文本视频上传允许的 MIME 类型。 */
|
|
105
|
+
const VIDEO_MIME_TYPES = ["video/mp4"];
|
|
106
|
+
/** 富文本视频上传大小上限(MB)。 */
|
|
107
|
+
const VIDEO_MAX_SIZE = 20;
|
|
108
|
+
|
|
109
|
+
// 图片上传前判断
|
|
110
|
+
const uploadImgValidate = (file: File): boolean => {
|
|
111
|
+
const sizeValid = file.size / 1024 / 1024 < IMAGE_MAX_SIZE;
|
|
112
|
+
const typeValid = IMAGE_MIME_TYPES.includes(file.type);
|
|
113
|
+
if (!typeValid) {
|
|
114
|
+
ElNotification({
|
|
115
|
+
title: t("common.title.warning"),
|
|
116
|
+
message: t("core.upload.image_format_invalid"),
|
|
117
|
+
type: "warning"
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (!sizeValid) {
|
|
121
|
+
ElNotification({
|
|
122
|
+
title: t("common.title.warning"),
|
|
123
|
+
message: t("core.upload.image_size_exceeded", { size: IMAGE_MAX_SIZE }),
|
|
124
|
+
type: "warning"
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return typeValid && sizeValid;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// 视频上传前判断
|
|
131
|
+
const uploadVideoValidate = (file: File): boolean => {
|
|
132
|
+
const sizeValid = file.size / 1024 / 1024 < VIDEO_MAX_SIZE;
|
|
133
|
+
const typeValid = VIDEO_MIME_TYPES.includes(file.type);
|
|
134
|
+
if (!typeValid) {
|
|
135
|
+
ElNotification({
|
|
136
|
+
title: t("common.title.warning"),
|
|
137
|
+
message: t("core.upload.file_format_invalid"),
|
|
138
|
+
type: "warning"
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (!sizeValid) {
|
|
142
|
+
ElNotification({
|
|
143
|
+
title: t("common.title.warning"),
|
|
144
|
+
message: t("core.upload.file_size_exceeded", { size: VIDEO_MAX_SIZE }),
|
|
145
|
+
type: "warning"
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return typeValid && sizeValid;
|
|
149
|
+
};
|
|
150
|
+
|
|
104
151
|
type InsertFnTypeImg = (url: string, alt?: string, href?: string) => void;
|
|
105
152
|
editorMenuConfig["uploadImage"] = {
|
|
106
153
|
async customUpload(file: File, insertFn: InsertFnTypeImg) {
|
|
@@ -114,12 +161,6 @@ editorMenuConfig["uploadImage"] = {
|
|
|
114
161
|
}
|
|
115
162
|
};
|
|
116
163
|
|
|
117
|
-
// 图片上传前判断
|
|
118
|
-
const uploadImgValidate = (file: File): boolean => {
|
|
119
|
-
console.log(file);
|
|
120
|
-
return true;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
164
|
/**
|
|
124
165
|
* @description 视频自定义上传
|
|
125
166
|
* @param file 上传的文件
|
|
@@ -138,12 +179,6 @@ editorMenuConfig["uploadVideo"] = {
|
|
|
138
179
|
}
|
|
139
180
|
};
|
|
140
181
|
|
|
141
|
-
// 视频上传前判断
|
|
142
|
-
const uploadVideoValidate = (file: File): boolean => {
|
|
143
|
-
console.log(file);
|
|
144
|
-
return true;
|
|
145
|
-
};
|
|
146
|
-
|
|
147
182
|
// 编辑框失去焦点时触发
|
|
148
183
|
const handleBlur = () => {
|
|
149
184
|
formItemContext?.prop && formContext?.validateField([formItemContext.prop as string]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ElNotification } from "element-plus";
|
|
1
|
+
import { ElMessage, ElNotification } from "element-plus";
|
|
2
2
|
import { t } from "../locales";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -26,7 +26,7 @@ export const useDownload = async (
|
|
|
26
26
|
}
|
|
27
27
|
try {
|
|
28
28
|
const res = await api(params);
|
|
29
|
-
const blob = new Blob([res]);
|
|
29
|
+
const blob = new Blob([res], { type: resolveBlobMimeType(fileType) });
|
|
30
30
|
// 兼容 edge 不支持 createObjectURL 方法
|
|
31
31
|
if ("msSaveOrOpenBlob" in navigator) return window.navigator.msSaveOrOpenBlob(blob, tempName + fileType);
|
|
32
32
|
const blobUrl = window.URL.createObjectURL(blob);
|
|
@@ -39,7 +39,19 @@ export const useDownload = async (
|
|
|
39
39
|
// 去除下载对 url 的影响
|
|
40
40
|
document.body.removeChild(exportFile);
|
|
41
41
|
window.URL.revokeObjectURL(blobUrl);
|
|
42
|
-
} catch
|
|
43
|
-
|
|
42
|
+
} catch {
|
|
43
|
+
ElMessage.error(t("common.message.request_error"));
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
|
+
|
|
47
|
+
/** 根据导出文件后缀返回对应的 Blob MIME 类型。 */
|
|
48
|
+
function resolveBlobMimeType(fileType: string) {
|
|
49
|
+
const mimeByExtension: Record<string, string> = {
|
|
50
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
51
|
+
".xls": "application/vnd.ms-excel",
|
|
52
|
+
".csv": "text/csv;charset=utf-8",
|
|
53
|
+
".pdf": "application/pdf",
|
|
54
|
+
".zip": "application/zip"
|
|
55
|
+
};
|
|
56
|
+
return mimeByExtension[fileType.toLowerCase()] ?? "application/octet-stream";
|
|
57
|
+
}
|
|
@@ -73,6 +73,13 @@ export const useTable = (
|
|
|
73
73
|
// Element Plus 要求分页总数为非负数字,兼容接口未返回总数的情况。
|
|
74
74
|
const total = Number(data.total ?? 0);
|
|
75
75
|
state.pageable.total = Number.isFinite(total) && total >= 0 ? total : 0;
|
|
76
|
+
// 删除末页最后一条后,当前页码可能超过总页数,回退到有效末页并重新查询,避免卡在空页。
|
|
77
|
+
const pageSize = state.pageable.page_size > 0 ? state.pageable.page_size : 1;
|
|
78
|
+
const maxPage = Math.max(1, Math.ceil(state.pageable.total / pageSize));
|
|
79
|
+
if (state.pageable.page_num > maxPage) {
|
|
80
|
+
state.pageable.page_num = maxPage;
|
|
81
|
+
return getTableList();
|
|
82
|
+
}
|
|
76
83
|
}
|
|
77
84
|
} catch (error) {
|
|
78
85
|
if (currentRequestSerial !== requestSerial) return;
|
|
@@ -340,8 +340,9 @@ service.interceptors.response.use(
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
const responseData = response.data as ErrorResponseData;
|
|
343
|
-
const { code, message
|
|
344
|
-
|
|
343
|
+
const { code, message } = responseData;
|
|
344
|
+
// 成功响应不携带错误码;只要存在 code 即视为结构化错误响应。
|
|
345
|
+
if (code === undefined) {
|
|
345
346
|
return response.data;
|
|
346
347
|
}
|
|
347
348
|
|