@jx3box/jx3box-editor 2.2.45 → 2.2.47
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.
- package/assets/css/article.less +1 -0
- package/assets/css/tinymce/voice.less +331 -0
- package/assets/js/audio.js +249 -0
- package/package.json +1 -1
- package/public/css/article.css +316 -0
- package/public/tinymce.html +9 -7
- package/src/Article.vue +3 -0
- package/src/ArticleMarkdown.vue +3 -0
- package/src/Tinymce.vue +190 -137
- package/test-audio.html +121 -0
package/src/Tinymce.vue
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
<div class="c-editor-tinymce">
|
|
3
|
+
<slot name="prepend"></slot>
|
|
4
|
+
|
|
5
|
+
<div class="c-editor-header">
|
|
6
|
+
<Upload v-if="attachmentEnable" @insert="insertAttachments" />
|
|
7
|
+
<Resource v-if="resourceEnable" @insert="insertResource" />
|
|
8
|
+
<BoxResource v-if="resourceEnable" @insert="insertResource" :subtype="subtype" />
|
|
9
|
+
</div>
|
|
10
|
+
<Emotion class="c-editor-emotion" @selected="emotionSelected"></Emotion>
|
|
11
|
+
|
|
12
|
+
<slot></slot>
|
|
13
|
+
|
|
14
|
+
<editor id="tinymce" v-model="data" :init="init" class="c-tinymce" placeholder="✔ 图片可右键粘贴或拖拽至编辑器内自动上传 ✔ 支持word/excel内容一键粘贴" />
|
|
15
|
+
<el-alert class="u-tutorial" type="warning" show-icon
|
|
16
|
+
>进入特殊区域(代码块,折叠块等等)脱离或使用工具栏触发后,请使用键盘方向 → ↓ 键进行脱离,回车只是正常在区块内换行。去掉样式点击第二行第一个<清除格式>即可复位。<a
|
|
17
|
+
href="/collection/31"
|
|
18
|
+
target="_blank"
|
|
19
|
+
>[编辑器使用指南]</a
|
|
20
|
+
>
|
|
21
|
+
</el-alert>
|
|
22
|
+
|
|
23
|
+
<slot name="append"></slot>
|
|
24
|
+
</div>
|
|
19
25
|
</template>
|
|
20
26
|
|
|
21
27
|
<script>
|
|
@@ -36,133 +42,180 @@ import { draggable } from "../assets/js/drag";
|
|
|
36
42
|
Vue.directive("draggable", draggable);
|
|
37
43
|
|
|
38
44
|
export default {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
45
|
+
name: "Tinymce",
|
|
46
|
+
props: ["content", "height", "attachmentEnable", "resourceEnable", "subtype"],
|
|
47
|
+
data: function () {
|
|
48
|
+
return {
|
|
49
|
+
data: this.content,
|
|
50
|
+
init: {
|
|
51
|
+
// 选择器
|
|
52
|
+
selector: "#tinymce",
|
|
53
|
+
|
|
54
|
+
// 语言
|
|
55
|
+
language: "zh_CN",
|
|
56
|
+
|
|
57
|
+
// 设置
|
|
58
|
+
convert_urls: false,
|
|
59
|
+
|
|
60
|
+
// 样式
|
|
61
|
+
// TODO:
|
|
62
|
+
content_css: process.env.VUE_APP_DEV_COMPONENT == "true" ? "/css/article.css" : `https://cdn.jx3box.com/static/jx3box-editor/css/article.css`,
|
|
63
|
+
// content_css: `http://localhost:3000/skins/content/default/content.min.css`,
|
|
64
|
+
body_class: "c-article c-article-editor c-article-tinymce",
|
|
65
|
+
height: this.height || 800,
|
|
66
|
+
autosave_ask_before_unload: false,
|
|
67
|
+
content_style: "",
|
|
68
|
+
|
|
69
|
+
// UI
|
|
70
|
+
icons: "custom",
|
|
71
|
+
menubar: false,
|
|
72
|
+
branding: false,
|
|
73
|
+
contextmenu: "",
|
|
74
|
+
plugins: [
|
|
75
|
+
"link autolink",
|
|
76
|
+
"hr lists advlist table codeinline codesample checklist foldtext latex anchor",
|
|
77
|
+
"image emoticons media videox macro qixue talent2",
|
|
78
|
+
"code fullscreen wordcount powerpaste pagebreak printpage pz audiox", // template anchor jx3icon autosave
|
|
79
|
+
],
|
|
80
|
+
toolbar: [
|
|
81
|
+
"undo | formatselect | fontsizeselect | forecolor backcolor | bold italic underline strikethrough superscript subscript | link unlink | fullscreen code", //anchor restoredraft
|
|
82
|
+
"removeformat | hr alignleft aligncenter alignright alignjustify indent outdent | bullist numlist checklist table blockquote foldtext codeinline codesample latex | emoticons image media videox audiox | macro pz qixue talent2 pagebreak printpage", // template anchor jx3icon
|
|
83
|
+
],
|
|
84
|
+
mobile: {
|
|
85
|
+
toolbar_drawer: true,
|
|
86
|
+
toolbar: [
|
|
87
|
+
"undo emoticons bold italic underline strikethrough superscript subscript link unlink forecolor backcolor removeformat pagebreak fullscreen code",
|
|
88
|
+
"hr alignleft aligncenter alignright alignjustify indent outdent bullist numlist checklist table blockquote foldtext codeinline codesample latex macro pz qixue talent2 media videox audiox",
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
block_formats: "段落=p;一级标题=h1;二级标题=h2;三级标题=h3;四级标题=h4;五级标题=h5;六级标题=h6;",
|
|
92
|
+
fontsize_formats: "12px 14px 16px 18px 22px 24px 26px 28px 32px 48px 72px",
|
|
93
|
+
color_map: [
|
|
94
|
+
"FF99CC",
|
|
95
|
+
"浅粉",
|
|
96
|
+
"FF3399",
|
|
97
|
+
"深粉",
|
|
98
|
+
"FF0000",
|
|
99
|
+
"正红",
|
|
100
|
+
"CC99FF",
|
|
101
|
+
"紫色",
|
|
102
|
+
"9933ff",
|
|
103
|
+
"深紫",
|
|
104
|
+
"FFFF99",
|
|
105
|
+
"浅黄",
|
|
106
|
+
"FFFF00",
|
|
107
|
+
"金黄",
|
|
108
|
+
"FFCC00",
|
|
109
|
+
"亮黄",
|
|
110
|
+
"FFCC99",
|
|
111
|
+
"浅桃",
|
|
112
|
+
"FF6600",
|
|
113
|
+
"橘色",
|
|
114
|
+
"CCFFCC",
|
|
115
|
+
"浅绿",
|
|
116
|
+
"9bf915",
|
|
117
|
+
"荧光绿",
|
|
118
|
+
"00FF00",
|
|
119
|
+
"辣眼绿",
|
|
120
|
+
"49c10f",
|
|
121
|
+
"深绿",
|
|
122
|
+
"008080",
|
|
123
|
+
"深青",
|
|
124
|
+
"CCFFFF",
|
|
125
|
+
"浅蓝",
|
|
126
|
+
"00FFFF",
|
|
127
|
+
"参考线",
|
|
128
|
+
"00CCFF",
|
|
129
|
+
"天蓝",
|
|
130
|
+
"99CCFF",
|
|
131
|
+
"蔚蓝",
|
|
132
|
+
"0000FF",
|
|
133
|
+
"辣眼蓝",
|
|
134
|
+
"CC0000",
|
|
135
|
+
"深红",
|
|
136
|
+
"000000",
|
|
137
|
+
"黑色",
|
|
138
|
+
],
|
|
139
|
+
|
|
140
|
+
codesample_languages: hljs_languages,
|
|
141
|
+
|
|
142
|
+
// Image
|
|
143
|
+
image_advtab: true,
|
|
144
|
+
// paste_data_images: true,
|
|
145
|
+
file_picker_types: "file image",
|
|
146
|
+
images_upload_url: API,
|
|
147
|
+
automatic_uploads: true,
|
|
148
|
+
images_upload_credentials: true,
|
|
149
|
+
|
|
150
|
+
// Hook
|
|
151
|
+
// setup: this.setup,
|
|
152
|
+
// init_instance_callback: this.ready,
|
|
153
|
+
|
|
154
|
+
// Template
|
|
155
|
+
// templates: [
|
|
156
|
+
// {
|
|
157
|
+
// title: "剑三宏",
|
|
158
|
+
// description: "",
|
|
159
|
+
// content: `
|
|
160
|
+
// <pre class="e-jx3macro-area w-jx3macro">/cast 自绝经脉</pre>
|
|
161
|
+
// `,
|
|
162
|
+
// },
|
|
163
|
+
// ],
|
|
164
|
+
valid_children: "+body[style]",
|
|
165
|
+
},
|
|
166
|
+
mode: "tinymce",
|
|
167
|
+
style: "",
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
model: {
|
|
171
|
+
prop: "content",
|
|
172
|
+
event: "update",
|
|
173
|
+
},
|
|
174
|
+
watch: {
|
|
175
|
+
data: function (newval) {
|
|
176
|
+
this.$emit("update", newval);
|
|
177
|
+
},
|
|
178
|
+
content: function (newval) {
|
|
179
|
+
this.data = newval;
|
|
180
|
+
},
|
|
181
|
+
style(val) {
|
|
182
|
+
this.init.content_style = val;
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
methods: {
|
|
186
|
+
setup: function (editor) {
|
|
187
|
+
// console.log("ID为: " + editor.id + " 的编辑器即将初始化.");
|
|
188
|
+
},
|
|
189
|
+
ready: function (editor) {
|
|
190
|
+
// console.log("ID为: " + editor.id + " 的编辑器已初始化完成.");
|
|
191
|
+
},
|
|
192
|
+
insertAttachments: function (data) {
|
|
193
|
+
tinyMCE.editors["tinymce"].insertContent(data.html);
|
|
194
|
+
},
|
|
195
|
+
insertResource: function (data) {
|
|
196
|
+
tinyMCE.editors["tinymce"].insertContent(data);
|
|
197
|
+
},
|
|
198
|
+
emotionSelected: function (emotion) {
|
|
199
|
+
let src = emotion.filename;
|
|
146
200
|
if (!emotion.filename.startsWith("http")) {
|
|
147
201
|
src = `${__imgPath}emotion/output/${emotion.filename}`;
|
|
148
202
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
203
|
+
const IMAGE = `<img class="t-emotion" src="${src}" alt="${src}" style="max-width:60px;max-height:60px" />`;
|
|
204
|
+
tinyMCE.editors["tinymce"].insertContent(IMAGE);
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
mounted: function () {},
|
|
208
|
+
components: {
|
|
209
|
+
Editor,
|
|
210
|
+
Upload,
|
|
211
|
+
Resource,
|
|
212
|
+
Emotion,
|
|
213
|
+
BoxResource,
|
|
214
|
+
},
|
|
161
215
|
};
|
|
162
216
|
</script>
|
|
163
217
|
|
|
164
218
|
<style lang="less">
|
|
165
219
|
@import "../assets/css/tinymce.less";
|
|
166
220
|
@import "../assets/css/tinymce/combo.less";
|
|
167
|
-
|
|
168
221
|
</style>
|
package/test-audio.html
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>音频播放器测试</title>
|
|
7
|
+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
11
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
12
|
+
min-height: 100vh;
|
|
13
|
+
padding: 40px 20px;
|
|
14
|
+
margin: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.container {
|
|
18
|
+
max-width: 800px;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
h1 {
|
|
23
|
+
color: white;
|
|
24
|
+
text-align: center;
|
|
25
|
+
margin-bottom: 40px;
|
|
26
|
+
font-size: 32px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.demo-section {
|
|
30
|
+
background: white;
|
|
31
|
+
border-radius: 15px;
|
|
32
|
+
padding: 30px;
|
|
33
|
+
margin-bottom: 30px;
|
|
34
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.demo-section h2 {
|
|
38
|
+
margin-top: 0;
|
|
39
|
+
color: #333;
|
|
40
|
+
border-bottom: 2px solid #9b87f5;
|
|
41
|
+
padding-bottom: 10px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.code-block {
|
|
45
|
+
background: #f5f5f5;
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
padding: 15px;
|
|
48
|
+
margin: 15px 0;
|
|
49
|
+
overflow-x: auto;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.code-block code {
|
|
53
|
+
font-family: "Monaco", "Courier New", monospace;
|
|
54
|
+
font-size: 14px;
|
|
55
|
+
color: #333;
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
58
|
+
</head>
|
|
59
|
+
<body>
|
|
60
|
+
<div class="container">
|
|
61
|
+
<h1>🎵 JX3 音频播放器演示</h1>
|
|
62
|
+
|
|
63
|
+
<div class="demo-section">
|
|
64
|
+
<h2>使用示例</h2>
|
|
65
|
+
<p>在文章内容中插入以下格式的文本,会自动渲染为音频播放器:</p>
|
|
66
|
+
<div class="code-block">
|
|
67
|
+
<code>name:123;author:1231;user_id:8719;src:https://cdn.jx3box.com/upload/voice/jx3cxk/2026/8719-1768912381447.mp3</code>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="demo-section">
|
|
72
|
+
<h2>实际效果</h2>
|
|
73
|
+
<div class="w-audio">name:123;author:1231;user_id:8719;src:https://cdn.jx3box.com/upload/voice/jx3cxk/2026/8719-1768912381447.mp3</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="demo-section">
|
|
77
|
+
<h2>功能特性</h2>
|
|
78
|
+
<ul>
|
|
79
|
+
<li>✨ 美观的紫色渐变卡片设计</li>
|
|
80
|
+
<li>🎨 旋转的黑胶唱片动画效果</li>
|
|
81
|
+
<li>🎯 可拖拽的进度条</li>
|
|
82
|
+
<li>⏯️ 播放/暂停控制</li>
|
|
83
|
+
<li>⏱️ 实时时间显示</li>
|
|
84
|
+
<li>📱 响应式设计,支持移动端</li>
|
|
85
|
+
<li>🎼 唱针动画效果</li>
|
|
86
|
+
</ul>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="demo-section">
|
|
90
|
+
<h2>在项目中使用</h2>
|
|
91
|
+
<p><strong>1. 导入模块:</strong></p>
|
|
92
|
+
<div class="code-block">
|
|
93
|
+
<code>import renderVoice from '@/assets/js/voice.js';</code>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<p><strong>2. 在组件挂载后调用:</strong></p>
|
|
97
|
+
<div class="code-block">
|
|
98
|
+
<code
|
|
99
|
+
>mounted() {<br />
|
|
100
|
+
renderVoice('.w-audio');<br />
|
|
101
|
+
}</code
|
|
102
|
+
>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<p><strong>3. HTML 中使用:</strong></p>
|
|
106
|
+
<div class="code-block">
|
|
107
|
+
<code><div class="w-audio">name:音频名称;author:作者;user_id:123;src:音频地址</div></code>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<script type="module">
|
|
113
|
+
import renderVoice from "./assets/js/voice.js";
|
|
114
|
+
|
|
115
|
+
// 页面加载完成后渲染音频播放器
|
|
116
|
+
$(document).ready(function () {
|
|
117
|
+
renderVoice(".w-audio");
|
|
118
|
+
});
|
|
119
|
+
</script>
|
|
120
|
+
</body>
|
|
121
|
+
</html>
|