@jx3box/jx3box-editor 2.2.48 → 3.0.0

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.
Files changed (175) hide show
  1. package/config/global.js +79 -0
  2. package/config/global.less +16 -0
  3. package/index.js +21 -8
  4. package/package.json +64 -63
  5. package/readme.md +25 -99
  6. package/src/Article.vue +96 -57
  7. package/src/ArticleMarkdown.vue +54 -47
  8. package/src/BoxResource.vue +67 -42
  9. package/src/Buff.vue +18 -7
  10. package/src/GameText.vue +32 -45
  11. package/src/Item.vue +143 -235
  12. package/src/ItemSimple.vue +27 -37
  13. package/src/Markdown.vue +362 -210
  14. package/src/Npc.vue +51 -30
  15. package/src/Resource.vue +296 -252
  16. package/src/Skill.vue +36 -26
  17. package/src/Tinymce.vue +124 -137
  18. package/src/Upload.vue +238 -155
  19. package/src/UploadAlbum.vue +189 -118
  20. package/{assets → src/assets}/css/article.less +1 -0
  21. package/src/assets/css/markdown.less +4 -0
  22. package/{assets → src/assets}/css/module/author.less +4 -3
  23. package/{assets → src/assets}/css/module/directory.less +23 -32
  24. package/{assets → src/assets}/css/module/talent.less +2 -2
  25. package/{assets → src/assets}/css/resource.less +56 -22
  26. package/src/assets/css/tinymce/_.less +28 -0
  27. package/src/assets/css/tinymce/a.less +21 -0
  28. package/{assets → src/assets}/css/tinymce/code.less +1 -1
  29. package/{assets/css → src/assets/css/tinymce}/combo.less +123 -18
  30. package/{assets → src/assets}/css/tinymce/fold.less +3 -6
  31. package/src/assets/css/tinymce/h.less +90 -0
  32. package/{assets → src/assets}/css/tinymce/latex.less +14 -14
  33. package/{assets → src/assets}/css/tinymce/macro.less +3 -3
  34. package/{assets → src/assets}/css/tinymce/pz.less +2 -2
  35. package/{assets → src/assets}/css/tinymce/table.less +5 -10
  36. package/{assets → src/assets}/css/tinymce.less +8 -4
  37. package/src/assets/css/upload.less +195 -0
  38. package/src/assets/css/upload_album.less +164 -0
  39. package/src/assets/css/var.less +2 -0
  40. package/src/assets/img/other/qr-code.svg +1 -0
  41. package/{assets → src/assets}/js/audio.js +2 -2
  42. package/{assets → src/assets}/js/directory.js +51 -23
  43. package/src/assets/js/hljs_languages.js +177 -0
  44. package/src/assets/js/katex.js +211 -0
  45. package/src/assets/js/renderImgPreview.js +49 -0
  46. package/{assets → src/assets}/js/xss.js +48 -5
  47. package/src/components/Author.vue +32 -13
  48. package/src/components/Avatar.vue +22 -3
  49. package/src/components/Combo.vue +118 -72
  50. package/src/components/PostAuthor.vue +13 -11
  51. package/src/components/QRcode.vue +136 -0
  52. package/src/components/SkillMartial.vue +13 -12
  53. package/src/pages/article.js +14 -0
  54. package/src/pages/index.js +5 -0
  55. package/src/pages/markdown.js +14 -0
  56. package/src/pages/tinymce.js +49 -0
  57. package/src/pages/upload.js +14 -0
  58. package/{service → src/service}/author.js +2 -2
  59. package/{service → src/service}/cms.js +5 -3
  60. package/{service → src/service}/database.js +4 -2
  61. package/{service → src/service}/item.js +1 -1
  62. package/{service → src/service}/node.js +1 -1
  63. package/{service → src/service}/resource.js +1 -1
  64. package/src/views/article.vue +72 -0
  65. package/src/views/index.vue +11 -0
  66. package/src/views/markdown.vue +58 -0
  67. package/src/views/tinymce.vue +58 -0
  68. package/src/views/upload.vue +111 -0
  69. package/.env +0 -2
  70. package/.vscode/settings.json +0 -5
  71. package/assets/css/katex-fix.css +0 -20
  72. package/assets/css/tinymce/_.less +0 -30
  73. package/assets/css/tinymce/a.less +0 -30
  74. package/assets/css/tinymce/combo.less +0 -111
  75. package/assets/css/tinymce/h.less +0 -58
  76. package/assets/css/upload.less +0 -105
  77. package/assets/js/katex.js +0 -191
  78. package/assets/js/renderImgPreview.js +0 -25
  79. package/babel.config.js +0 -3
  80. package/docs/markdown.md +0 -16
  81. package/jsconfig.json +0 -9
  82. package/public/article.html +0 -15
  83. package/public/css/article.css +0 -2481
  84. package/public/css/article.less +0 -3
  85. package/public/favicon.ico +0 -0
  86. package/public/tinymce.html +0 -33
  87. package/src/Equip.vue +0 -301
  88. package/src/components/LetterDemo.vue +0 -93
  89. package/src/components/medal.vue +0 -43
  90. package/test-audio.html +0 -121
  91. package/vue.config.js +0 -147
  92. /package/{assets → src/assets}/css/markdown/_.less +0 -0
  93. /package/{assets → src/assets}/css/markdown/macro.less +0 -0
  94. /package/{assets/css/article_markdown.less → src/assets/css/markdown/markdown-article.less} +0 -0
  95. /package/{assets/css/markdown.less → src/assets/css/markdown/markdown-editor.less} +0 -0
  96. /package/{assets → src/assets}/css/markdown/talent.less +0 -0
  97. /package/{assets → src/assets}/css/markdown/video.less +0 -0
  98. /package/{assets → src/assets}/css/module/buff.less +0 -0
  99. /package/{assets → src/assets}/css/module/icon.less +0 -0
  100. /package/{assets → src/assets}/css/module/item.less +0 -0
  101. /package/{assets → src/assets}/css/module/item_simple.less +0 -0
  102. /package/{assets → src/assets}/css/module/jx3_element.less +0 -0
  103. /package/{assets → src/assets}/css/module/macro.less +0 -0
  104. /package/{assets → src/assets}/css/module/npc.less +0 -0
  105. /package/{assets → src/assets}/css/module/resource.less +0 -0
  106. /package/{assets → src/assets}/css/module/skill.less +0 -0
  107. /package/{assets → src/assets}/css/tinymce/hr.less +0 -0
  108. /package/{assets → src/assets}/css/tinymce/img.less +0 -0
  109. /package/{assets → src/assets}/css/tinymce/imgpreview.less +0 -0
  110. /package/{assets → src/assets}/css/tinymce/list.less +0 -0
  111. /package/{assets → src/assets}/css/tinymce/nextpage.less +0 -0
  112. /package/{assets → src/assets}/css/tinymce/p.less +0 -0
  113. /package/{assets → src/assets}/css/tinymce/plugin.less +0 -0
  114. /package/{assets → src/assets}/css/tinymce/qixue.less +0 -0
  115. /package/{assets → src/assets}/css/tinymce/quote.less +0 -0
  116. /package/{assets → src/assets}/css/tinymce/video.less +0 -0
  117. /package/{assets → src/assets}/css/tinymce/voice.less +0 -0
  118. /package/{assets → src/assets}/data/detach_type.json +0 -0
  119. /package/{assets → src/assets}/data/game_font.json +0 -0
  120. /package/{assets → src/assets}/data/markdown_whitelist.json +0 -0
  121. /package/{assets → src/assets}/data/weapon_type.json +0 -0
  122. /package/{assets → src/assets}/img/buff.svg +0 -0
  123. /package/{assets → src/assets}/img/equip_bg.png +0 -0
  124. /package/{assets → src/assets}/img/file.svg +0 -0
  125. /package/{assets → src/assets}/img/icons.svg +0 -0
  126. /package/{assets → src/assets}/img/item/pve.png +0 -0
  127. /package/{assets → src/assets}/img/item/pvp.png +0 -0
  128. /package/{assets → src/assets}/img/item/pvx.png +0 -0
  129. /package/{assets → src/assets}/img/item/std.png +0 -0
  130. /package/{assets → src/assets}/img/item/wujie.png +0 -0
  131. /package/{assets → src/assets}/img/item.svg +0 -0
  132. /package/{assets → src/assets}/img/jx3.svg +0 -0
  133. /package/{assets → src/assets}/img/jx3box.svg +0 -0
  134. /package/{assets → src/assets}/img/npc/attack.svg +0 -0
  135. /package/{assets → src/assets}/img/npc/buff.svg +0 -0
  136. /package/{assets → src/assets}/img/npc/energy.svg +0 -0
  137. /package/{assets → src/assets}/img/npc/miss.svg +0 -0
  138. /package/{assets → src/assets}/img/npc/npc.svg +0 -0
  139. /package/{assets → src/assets}/img/npc/radar.svg +0 -0
  140. /package/{assets → src/assets}/img/npc/shield.svg +0 -0
  141. /package/{assets → src/assets}/img/npc/sight.svg +0 -0
  142. /package/{assets → src/assets}/img/npc/skull.svg +0 -0
  143. /package/{assets → src/assets}/img/npc/target.svg +0 -0
  144. /package/{assets → src/assets}/img/skill.svg +0 -0
  145. /package/{assets → src/assets}/img/skillset.png +0 -0
  146. /package/{assets → src/assets}/js/a.js +0 -0
  147. /package/{assets → src/assets}/js/code.js +0 -0
  148. /package/{assets → src/assets}/js/combo.js +0 -0
  149. /package/{assets → src/assets}/js/drag.js +0 -0
  150. /package/{assets → src/assets}/js/filter2.js +0 -0
  151. /package/{assets → src/assets}/js/fold.js +0 -0
  152. /package/{assets → src/assets}/js/gallery.js +0 -0
  153. /package/{assets → src/assets}/js/iframe.js +0 -0
  154. /package/{assets → src/assets}/js/img.js +0 -0
  155. /package/{assets → src/assets}/js/item/attribute_percent.js +0 -0
  156. /package/{assets → src/assets}/js/item/bind.js +0 -0
  157. /package/{assets → src/assets}/js/item/border.js +0 -0
  158. /package/{assets → src/assets}/js/item/border_quest.js +0 -0
  159. /package/{assets → src/assets}/js/item/color.js +0 -0
  160. /package/{assets → src/assets}/js/item/hljs_languages.js +0 -0
  161. /package/{assets → src/assets}/js/item/icon_url.js +0 -0
  162. /package/{assets → src/assets}/js/item/second_format.js +0 -0
  163. /package/{assets → src/assets}/js/jx3_element.js +0 -0
  164. /package/{assets → src/assets}/js/macro.js +0 -0
  165. /package/{assets → src/assets}/js/nextpage.js +0 -0
  166. /package/{assets → src/assets}/js/pswp.js +0 -0
  167. /package/{assets → src/assets}/js/pswp_template.js +0 -0
  168. /package/{assets → src/assets}/js/pz_iframe.js +0 -0
  169. /package/{assets → src/assets}/js/qixue.js +0 -0
  170. /package/{assets → src/assets}/js/script.js +0 -0
  171. /package/{assets → src/assets}/js/talent2.js +0 -0
  172. /package/{assets → src/assets}/js/tex-mml-chtml.js +0 -0
  173. /package/{service → src/service}/enum/CollectionPublic.js +0 -0
  174. /package/{service → src/service}/enum/EquipPosition.js +0 -0
  175. /package/{service → src/service}/enum/EquipType.js +0 -0
package/src/Upload.vue CHANGED
@@ -1,68 +1,104 @@
1
1
  <template>
2
2
  <div class="c-upload">
3
- <!-- 上传触发按钮 -->
4
- <el-button type="primary" @click="dialogVisible = true" icon="el-icon-upload" :disabled="!enable">{{ btn_txt }}</el-button>
5
-
6
- <!-- 弹出界面 -->
7
- <el-dialog class="c-large-dialog" title="上传" :visible.sync="dialogVisible">
8
- <!-- 清空按钮 -->
9
- <el-button class="u-upload-clear" plain icon="el-icon-delete" size="mini" @click="clear">清空</el-button>
10
-
11
- <!-- 限制提示 -->
12
- <el-alert class="u-upload-tip" :title="tip" type="info" show-icon :closable="false"></el-alert>
13
-
14
- <!-- 文件区 -->
15
- <el-upload :action="API" list-type="picture-card" :auto-upload="false" :limit="10" multiple with-credentials :file-list="fileList" :on-change="change" ref="uploadbox" :accept="accept">
16
- <!-- :accept="accept" -->
17
- <i slot="default" class="el-icon-plus"></i>
18
-
19
- <!-- 文件项 -->
20
- <div
21
- slot="file"
22
- slot-scope="{ file }"
23
- class="u-file-wrapper"
24
- @click="select(file)"
25
- :class="{
26
- isSelected: file.selected,
27
- disabled: file.status != 'success',
28
- }"
3
+ <el-button type="primary" :disabled="!enable" @click="dialogVisible = true">
4
+ <el-icon><UploadFilled /></el-icon>
5
+ <span>{{ buttonText }}</span>
6
+ </el-button>
7
+
8
+ <el-dialog v-model="dialogVisible" class="c-large-dialog" title="上传">
9
+ <div class="c-upload-toolbar">
10
+ <!-- 清空按钮 -->
11
+ <el-button class="u-upload-clear" plain size="small" @click="clear"
12
+ ><el-icon> <Delete /> </el-icon><span>清空</span></el-button
29
13
  >
30
- <!-- 图片类型 -->
31
- <img v-if="file.is_img" class="el-upload-list__item-thumbnail u-imgbox" :src="file.url" alt />
32
- <!-- 其他类型 -->
33
- <div v-else class="u-filebox">
34
- <img class="u-fileplaceholder" svg-inline src="../assets/img/file.svg" />
35
- <span class="u-filename">{{ file.name }}</span>
14
+ <!-- 限制提示 -->
15
+ <div class="u-upload-tip" :title="tipText" type="info" show-icon :closable="false"><span>{{ tipText }}</span></div>
16
+ </div>
17
+
18
+ <el-upload
19
+ list-type="picture-card"
20
+ :auto-upload="false"
21
+ :limit="max"
22
+ multiple
23
+ :file-list="fileList"
24
+ :on-change="change"
25
+ ref="uploadbox"
26
+ :accept="accept"
27
+ with-credentials
28
+ >
29
+ <template #default>
30
+ <el-icon><Plus /></el-icon>
31
+ </template>
32
+
33
+ <template #file="{ file }">
34
+ <div
35
+ class="u-file-wrapper"
36
+ @click.stop="select(file)"
37
+ :class="{
38
+ isSelected: !!file.selected,
39
+ isUnselected: !file.selected,
40
+ isPending: !!file.status && file.status !== 'success',
41
+ }"
42
+ v-loading="file.status === 'uploading'"
43
+ >
44
+ <template v-if="isImageFile(file)">
45
+ <img
46
+ class="el-upload-list__item-thumbnail u-imgbox"
47
+ :src="file.url"
48
+ :data-upload-uid="file.uid"
49
+ alt=""
50
+ />
51
+ <i class="u-mask"></i>
52
+ <span class="u-op u-preview-btn" @click.stop="preview(file, $event)">
53
+ <el-icon><ZoomIn /></el-icon>
54
+ </span>
55
+ </template>
56
+ <span
57
+ class="u-op u-delete-btn"
58
+ :class="{ 'is-single': !isImageFile(file) }"
59
+ @click.stop="deleteFile(file)"
60
+ >
61
+ <el-icon><Delete /></el-icon>
62
+ </span>
63
+ <div v-if="!isImageFile(file)" class="u-filebox">
64
+ <img class="u-fileplaceholder" svg-inline src="./assets/img/file.svg" />
65
+ <span class="u-filename">{{ file.name }}</span>
66
+ </div>
67
+ <label class="u-file-select-label" :class="{ 'is-unselected': !file.selected }">
68
+ <span class="u-file-select-icon">✓</span>
69
+ </label>
36
70
  </div>
37
- <!-- 勾选角标 -->
38
- <label v-show="file.selected" class="u-file-select-label">
39
- <i class="el-icon-upload-success el-icon-check"></i>
40
- </label>
41
- </div>
71
+ </template>
42
72
  </el-upload>
43
73
 
44
- <!-- 插入按钮 -->
45
- <span slot="footer" class="dialog-footer">
74
+ <template #footer>
46
75
  <el-button @click="dialogVisible = false">取 消</el-button>
47
76
  <el-button type="primary" @click="insert">
48
77
  {{ buttonTXT }}
49
78
  </el-button>
50
- </span>
79
+ </template>
51
80
  </el-dialog>
52
81
  </div>
53
82
  </template>
54
83
 
55
84
  <script>
56
85
  import axios from "axios";
57
- import { __cms } from "@jx3box/jx3box-common/data/jx3box.json";
58
- const API_Root = process.env.NODE_ENV === "production" ? __cms : "/";
59
- const API = API_Root + "api/cms/upload";
60
-
86
+ import { Delete, Plus, UploadFilled, ZoomIn } from "@element-plus/icons-vue";
87
+ import JX3BOX from "@jx3box/jx3box-common/data/jx3box.json";
61
88
  import allow_types from "@jx3box/jx3box-common/data/conf";
62
- const imgtypes = ["jpg", "png", "gif", "bmp", "webp", "jpeg", "JPG", "PNG", "GIF", "BMP", "WEBP", "JPEG"];
89
+ import { showImgPreview } from "./assets/js/renderImgPreview";
90
+ const { __cms } = JX3BOX;
91
+ const API = __cms + "api/cms/upload";
92
+ const imgtypes = ["jpg", "png", "gif", "bmp", "webp", "jpeg", "svg"];
63
93
 
64
94
  export default {
65
95
  name: "Upload",
96
+ components: {
97
+ Delete,
98
+ Plus,
99
+ UploadFilled,
100
+ ZoomIn,
101
+ },
66
102
  props: {
67
103
  text: {
68
104
  type: String,
@@ -75,6 +111,7 @@ export default {
75
111
  },
76
112
  accept: {
77
113
  type: String,
114
+ default: allow_types.accept,
78
115
  },
79
116
  enable: {
80
117
  type: Boolean,
@@ -87,162 +124,208 @@ export default {
87
124
  // 文件大小限制
88
125
  sizeLimit: {
89
126
  type: Number,
90
- default: 30
127
+ default: 30,
91
128
  },
92
129
  },
93
- data: function () {
130
+ emits: ["insert", "update", "htmlUpdate"],
131
+ data() {
94
132
  return {
95
- API: API,
96
133
  dialogVisible: false,
97
- tip: this.desc || `一次最多同时上传${this.max}个文件(单个文件不超过${this.sizeLimit}M),格式限常见的图片、文档、数据表及压缩包`,
98
- btn_txt: this.text || "上传附件",
99
-
100
134
  fileList: [],
101
- selectedCount: 0,
102
135
  insertList: "",
103
-
104
- // accept: allow_types.accept,
105
- // sizeLimit: allow_types.sizeLimit,
106
136
  };
107
137
  },
108
138
  watch: {
109
139
  fileList: {
110
140
  deep: true,
111
- handler: function (newval) {
141
+ handler(newval) {
112
142
  this.$emit("update", newval);
113
143
  },
114
144
  },
115
- insertList: function (newval) {
145
+ insertList(newval) {
116
146
  this.$emit("htmlUpdate", newval);
117
147
  },
118
148
  },
119
149
  computed: {
120
- buttonTXT: function () {
150
+ tipText() {
151
+ return (
152
+ this.desc ||
153
+ `一次最多同时上传${this.max}个文件(单个文件不超过${this.sizeLimit}M),格式限常见的图片、文档、数据表及压缩包`
154
+ );
155
+ },
156
+ buttonText() {
157
+ return this.text || "上传附件";
158
+ },
159
+ selectedCount() {
160
+ return this.fileList.filter((file) => file.selected).length;
161
+ },
162
+ buttonTXT() {
121
163
  return this.selectedCount ? "插 入" : "确 定";
122
164
  },
123
165
  },
124
166
  methods: {
125
- change: function (file, fileList) {
126
- if (file.status != "success") {
127
- // 判断大小
128
- // if (file.size > this.sizeLimit) {
129
- // this.$message.error("文件超出大小限制");
130
- // this.removeFile(fileList, file.uid);
131
- // return;
132
- // }
133
-
134
- // 分析文件类型
135
- let ext = file.name.split(".").pop();
136
- let is_img = imgtypes.includes(ext);
137
-
138
- if (this.onlyImage && !is_img) return;
139
-
140
- // 构建数据
141
- let fdata = new FormData();
142
- fdata.append("file", file.raw);
143
-
144
- // 异步上传
145
- axios
146
- .post(API, fdata, {
147
- headers: {
148
- "Content-Type": "multipart/form-data",
149
- },
150
- withCredentials: true,
151
- auth: {
152
- username: (localStorage && localStorage.getItem("token")) || "",
153
- password: "cms common request",
154
- },
155
- })
156
- .then((res) => {
157
- if (res.data.code) {
158
- this.$message({
159
- message: res.data.msg,
160
- type: "error",
161
- });
162
- return;
163
- }
164
- // 提醒
165
- this.$message({
166
- message: "上传成功",
167
- type: "success",
168
- });
169
-
170
- // 修改path
171
- file.url = res.data.data && res.data.data[0];
172
-
173
- // 额外赋值
174
- file.is_img = is_img;
175
- file.selected = true;
176
-
177
- // 修改状态加入仓库
178
- file.status = "success";
179
- this.fileList.push(file);
180
- this.selectedCount++;
181
- })
182
- .catch((err) => {
183
- if (err.response.data.code) {
184
- this.$message.error(`[${err.response.data.code}] ${err.response.data.message}`);
185
- } else {
186
- this.$message.error("请求异常");
187
- }
188
- });
167
+ normalizeUploadFile(file, extra = {}) {
168
+ const base = file || {};
169
+ return {
170
+ uid: base.uid,
171
+ name: base.name,
172
+ url: base.url,
173
+ status: base.status,
174
+ raw: base.raw,
175
+ selected: !!base.selected,
176
+ is_img: this.isImageFile(base),
177
+ ...extra,
178
+ };
179
+ },
180
+ upsertFile(file) {
181
+ const next = this.normalizeUploadFile(file);
182
+ const index = this.fileList.findIndex((item) => item.uid === next.uid);
183
+ if (index > -1) {
184
+ const list = [...this.fileList];
185
+ list.splice(index, 1, next);
186
+ this.fileList = list;
187
+ } else {
188
+ this.fileList = [...this.fileList, next];
189
189
  }
190
190
  },
191
- select: function (file) {
192
- if (file.status == "success") {
193
- this.$set(file, "selected", !file.selected);
194
- file.selected ? this.selectedCount++ : this.selectedCount--;
191
+ isImageFile(file) {
192
+ if (!file) return false;
193
+ if (typeof file.is_img === "boolean") return file.is_img;
194
+ if (file.raw?.type?.startsWith("image/")) return true;
195
+
196
+ const origin = file.name || file.url || "";
197
+ const clean = origin.split("?")[0].split("#")[0];
198
+ const ext = (clean.split(".").pop() || "").toLowerCase();
199
+ return imgtypes.includes(ext);
200
+ },
201
+ change(file) {
202
+ if (!file || file.status === "success" || !file.raw) return;
203
+
204
+ const ext = (file.name.split(".").pop() || "").toLowerCase();
205
+ const is_img = imgtypes.includes(ext);
206
+
207
+ if (this.onlyImage && !is_img) {
208
+ this.$message.warning("当前仅允许上传图片");
209
+ this.removeFileByUid(file.uid);
210
+ return;
195
211
  }
212
+
213
+ const sizeInMB = (file.size || 0) / 1024 / 1024;
214
+ if (sizeInMB > this.sizeLimit) {
215
+ this.$message.error(`文件超出大小限制(${this.sizeLimit}M)`);
216
+ this.removeFileByUid(file.uid);
217
+ return;
218
+ }
219
+
220
+ const fdata = new FormData();
221
+ fdata.append("file", file.raw);
222
+
223
+ axios
224
+ .post(API, fdata, {
225
+ headers: {
226
+ "Content-Type": "multipart/form-data",
227
+ },
228
+ withCredentials: true,
229
+ auth: {
230
+ username: (localStorage && localStorage.getItem("token")) || "",
231
+ password: "cms common request",
232
+ },
233
+ })
234
+ .then((res) => {
235
+ const payload = res.data || {};
236
+ if (payload.code) {
237
+ this.$message.error(payload.msg || "上传失败");
238
+ this.removeFileByUid(file.uid);
239
+ return;
240
+ }
241
+
242
+ const url =
243
+ payload.location ||
244
+ payload.url ||
245
+ (payload.data &&
246
+ (Array.isArray(payload.data)
247
+ ? payload.data[0]
248
+ : payload.data.url || payload.data.location || payload.data));
249
+
250
+ if (!url) {
251
+ this.$message.error("上传成功但未返回文件地址");
252
+ this.removeFileByUid(file.uid);
253
+ return;
254
+ }
255
+ this.upsertFile(
256
+ this.normalizeUploadFile(file, {
257
+ url,
258
+ is_img,
259
+ selected: true,
260
+ status: "success",
261
+ })
262
+ );
263
+
264
+ this.$message.success("上传成功");
265
+ })
266
+ .catch((err) => {
267
+ const code = err?.response?.data?.code;
268
+ const message = err?.response?.data?.message || err?.response?.data?.msg;
269
+ if (code) {
270
+ this.$message.error(`[${code}] ${message || "请求异常"}`);
271
+ } else {
272
+ this.$message.error("请求异常");
273
+ }
274
+ this.removeFileByUid(file.uid);
275
+ });
276
+ },
277
+ select(file) {
278
+ if (file.status && file.status !== "success") return;
279
+ this.fileList = this.fileList.map((item) =>
280
+ item.uid === file.uid ? { ...item, selected: !item.selected } : item
281
+ );
282
+ },
283
+ preview(file, e) {
284
+ if (!this.isImageFile(file) || !file.url) return;
285
+ const wrapper = e?.currentTarget?.closest?.(".u-file-wrapper");
286
+ const img = wrapper?.querySelector?.("img.u-imgbox");
287
+ if (!img) return;
288
+ showImgPreview(img);
196
289
  },
197
- buildHTML: function () {
198
- let list = [];
290
+ buildHTML() {
291
+ const list = [];
199
292
  this.fileList.forEach((file) => {
200
293
  if (file.selected) {
201
- file.is_img ? list.push(`<img src="${file.url}" />`) : list.push(`<a target="_blank" href="${file.url}">${file.name}</a>`);
294
+ this.isImageFile(file)
295
+ ? list.push(`<img src="${file.url}" />`)
296
+ : list.push(`<a target="_blank" href="${file.url}">${file.name}</a>`);
202
297
  }
203
298
  });
204
299
  this.insertList = list.join(" \n");
205
300
  return this.insertList;
206
301
  },
207
- insert: function () {
208
- // 关闭窗口
302
+ insert() {
209
303
  this.dialogVisible = false;
210
-
211
- //为空不执行插入
212
304
  if (!this.selectedCount) return;
213
-
214
- // 传递值
215
305
  this.$emit("insert", {
216
306
  list: this.fileList,
217
307
  html: this.buildHTML(),
218
308
  });
219
-
220
- //移除所有选择状态
221
309
  this.resetSelectStatus();
222
310
  },
223
- resetSelectStatus: function () {
224
- this.fileList.forEach((file, i) => {
225
- this.$set(this.fileList[i], "selected", false);
226
- });
227
- this.selectedCount = 0;
311
+ resetSelectStatus() {
312
+ this.fileList = this.fileList.map((file) => ({ ...file, selected: false }));
228
313
  },
229
- clear: function () {
230
- this.$refs.uploadbox.clearFiles();
314
+ clear() {
315
+ this.$refs.uploadbox?.clearFiles?.();
231
316
  this.fileList = [];
317
+ this.insertList = "";
232
318
  },
233
- removeFile: function (fileList, uid) {
234
- fileList.forEach((file, i) => {
235
- if (file.uid == uid) {
236
- fileList.splice(i, 1);
237
- }
238
- });
319
+ removeFileByUid(uid) {
320
+ if (!uid) return;
321
+ this.fileList = this.fileList.filter((file) => file.uid !== uid);
322
+ },
323
+ deleteFile(file) {
324
+ if (!file) return;
325
+ this.removeFileByUid(file.uid);
239
326
  },
240
327
  },
241
- mounted: function () {},
242
- components: {},
243
328
  };
244
329
  </script>
245
330
 
246
- <style lang="less">
247
- @import "../assets/css/upload.less";
248
- </style>
331
+ <style lang="less" src="./assets/css/upload.less"></style>