@liujitcn/kratos-admin-core 0.0.59 → 0.0.61

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
- const editorMenuConfig = props.editorConfig.MENU_CONF ?? {};
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.disable());
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
- * @description 图片自定义上传
101
- * @param file 上传的文件
102
- * @param insertFn 上传成功后的回调函数(插入到富文本编辑器中)
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 (error) {
43
- console.log(error);
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, reason, metadata } = responseData;
344
- if (code === undefined || message === undefined || reason === undefined || metadata === undefined) {
343
+ const { code, message } = responseData;
344
+ // 成功响应不携带错误码;只要存在 code 即视为结构化错误响应。
345
+ if (code === undefined) {
345
346
  return response.data;
346
347
  }
347
348
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@liujitcn/kratos-admin-core",
3
3
  "private": false,
4
- "version": "0.0.59",
4
+ "version": "0.0.61",
5
5
  "type": "module",
6
6
  "description": "kratos-admin frontend runtime and base modules",
7
7
  "author": {