Skip to content

Commit b133983

Browse files
author
Aix
committed
Merge remote-tracking branch 'origin/dev' into dev
2 parents ef4f6bd + f7fe794 commit b133983

File tree

10 files changed

+2056
-9
lines changed

10 files changed

+2056
-9
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<script setup>
2+
import { ref, reactive } from 'vue'
3+
import { QuillEditor } from '@vueup/vue-quill'
4+
import '@vueup/vue-quill/dist/vue-quill.snow.css'
5+
import { getAccessToken } from '@/utils/auth'
6+
import editorOptions from './quill-options'
7+
8+
const BASE_URL = import.meta.env.VITE_BASE_URL
9+
10+
const message = useMessage()
11+
12+
const props = defineProps({
13+
/* 公众号账号编号 */
14+
accountId: {
15+
type: Number,
16+
required: true
17+
},
18+
/* 编辑器的内容 */
19+
value: {
20+
type: String,
21+
default: ''
22+
},
23+
/* 图片大小 */
24+
maxSize: {
25+
type: Number,
26+
default: 4000 // kb
27+
}
28+
})
29+
30+
const emit = defineEmits(['input'])
31+
32+
const myQuillEditorRef = ref()
33+
34+
const content = ref(props.value.replace(/data-src/g, 'src'))
35+
36+
const loading = ref(false) // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
37+
38+
const actionUrl = ref(BASE_URL + '/admin-api/mp/material/upload-news-image') // 这里写你要上传的图片服务器地址
39+
const headers = ref({ Authorization: 'Bearer ' + getAccessToken() }) // 设置上传的请求头部
40+
const uploadData = reactive({
41+
type: 'image', // TODO 芋艿:试试要不要换成 thumb
42+
accountId: props.accountId
43+
})
44+
45+
const onEditorChange = () => {
46+
//内容改变事件
47+
emit('input', content.value)
48+
}
49+
50+
// 富文本图片上传前
51+
const beforeUpload = () => {
52+
// 显示 loading 动画
53+
loading.value = true
54+
}
55+
56+
// 图片上传成功
57+
// 注意!由于微信公众号的图片有访问限制,所以会显示“此图片来自微信公众号,未经允许不可引用”
58+
const uploadSuccess = (res) => {
59+
// res为图片服务器返回的数据
60+
// 获取富文本组件实例
61+
const quill = myQuillEditorRef.value.quill
62+
// 如果上传成功
63+
const link = res.data
64+
if (link) {
65+
// 获取光标所在位置
66+
let length = quill.getSelection().index
67+
// 插入图片 res.info为服务器返回的图片地址
68+
quill.insertEmbed(length, 'image', link)
69+
// 调整光标到最后
70+
quill.setSelection(length + 1)
71+
} else {
72+
message.error('图片插入失败')
73+
}
74+
// loading 动画消失
75+
loading.value = false
76+
}
77+
78+
// 富文本图片上传失败
79+
const uploadError = () => {
80+
// loading 动画消失
81+
loading.value = false
82+
message.error('图片插入失败')
83+
}
84+
</script>
85+
86+
<template>
87+
<div id="wxEditor">
88+
<div v-loading="loading" element-loading-text="请稍等,图片上传中">
89+
<!-- 图片上传组件辅助-->
90+
<el-upload
91+
class="avatar-uploader"
92+
name="file"
93+
:action="actionUrl"
94+
:headers="headers"
95+
:show-file-list="false"
96+
:data="uploadData"
97+
:on-success="uploadSuccess"
98+
:on-error="uploadError"
99+
:before-upload="beforeUpload"
100+
/>
101+
<QuillEditor
102+
class="editor"
103+
v-model="content"
104+
ref="quillEditorRef"
105+
:options="editorOptions"
106+
@change="onEditorChange($event)"
107+
/>
108+
</div>
109+
</div>
110+
</template>
111+
112+
<style>
113+
.editor {
114+
line-height: normal !important;
115+
height: 500px;
116+
}
117+
118+
.ql-snow .ql-tooltip[data-mode='link']::before {
119+
content: '请输入链接地址:';
120+
}
121+
122+
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
123+
border-right: 0;
124+
content: '保存';
125+
padding-right: 0;
126+
}
127+
128+
.ql-snow .ql-tooltip[data-mode='video']::before {
129+
content: '请输入视频地址:';
130+
}
131+
132+
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
133+
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
134+
content: '14px';
135+
}
136+
137+
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before,
138+
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before {
139+
content: '10px';
140+
}
141+
142+
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before,
143+
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before {
144+
content: '18px';
145+
}
146+
147+
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before,
148+
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before {
149+
content: '32px';
150+
}
151+
152+
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
153+
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
154+
content: '文本';
155+
}
156+
157+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
158+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
159+
content: '标题1';
160+
}
161+
162+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
163+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
164+
content: '标题2';
165+
}
166+
167+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
168+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
169+
content: '标题3';
170+
}
171+
172+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
173+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
174+
content: '标题4';
175+
}
176+
177+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
178+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
179+
content: '标题5';
180+
}
181+
182+
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
183+
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
184+
content: '标题6';
185+
}
186+
187+
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
188+
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
189+
content: '标准字体';
190+
}
191+
192+
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
193+
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
194+
content: '衬线字体';
195+
}
196+
197+
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
198+
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
199+
content: '等宽字体';
200+
}
201+
</style>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const toolbarOptions = [
2+
['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
3+
['blockquote', 'code-block'], // 引用 代码块
4+
[{ header: 1 }, { header: 2 }], // 1、2 级标题
5+
[{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
6+
[{ script: 'sub' }, { script: 'super' }], // 上标/下标
7+
[{ indent: '-1' }, { indent: '+1' }], // 缩进
8+
// [{'direction': 'rtl'}], // 文本方向
9+
[{ size: ['small', false, 'large', 'huge'] }], // 字体大小
10+
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
11+
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
12+
[{ font: [] }], // 字体种类
13+
[{ align: [] }], // 对齐方式
14+
['clean'], // 清除文本格式
15+
['link', 'image', 'video'] // 链接、图片、视频
16+
]
17+
18+
export default {
19+
theme: 'snow',
20+
placeholder: '请输入文章内容',
21+
modules: {
22+
toolbar: {
23+
container: toolbarOptions,
24+
// container: "#toolbar",
25+
handlers: {
26+
image: function (value) {
27+
if (value) {
28+
// 触发input框选择图片文件
29+
document.querySelector('.avatar-uploader input').click()
30+
} else {
31+
this.quill.format('image', false)
32+
}
33+
},
34+
link: function (value) {
35+
if (value) {
36+
const href = prompt('注意!只支持公众号图文链接')
37+
this.quill.format('link', href)
38+
} else {
39+
this.quill.format('link', false)
40+
}
41+
}
42+
}
43+
}
44+
}
45+
}

src/views/mp/components/wx-material-select/main.vue

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
</div>
3030
<!-- 类型:voice -->
3131
<div v-else-if="objData.type === 'voice'">
32+
<!-- 列表 -->
3233
<el-table v-loading="loading" :data="list">
3334
<el-table-column label="编号" align="center" prop="mediaId" />
3435
<el-table-column label="文件名" align="center" prop="name" />
@@ -47,7 +48,7 @@
4748
<el-table-column label="操作" align="center" fixed="right">
4849
<template #default="scope">
4950
<el-button type="text" @click="selectMaterialFun(scope.row)">
50-
选择 <Icon icon="ep:plus" />
51+
选择<Icon icon="ep:plus" />
5152
</el-button>
5253
</template>
5354
</el-table-column>
@@ -80,10 +81,15 @@
8081
width="180"
8182
:formatter="dateFormatter"
8283
/>
83-
<el-table-column label="操作" align="center">
84+
<el-table-column
85+
label="操作"
86+
align="center"
87+
fixed="right"
88+
class-name="small-padding fixed-width"
89+
>
8490
<template #default="scope">
85-
<el-button type="text" @click="selectMaterialFun(scope.row)"
86-
>选择<Icon icon="ep:circle-plus" />
91+
<el-button type="text" @click="selectMaterialFun(scope.row)">
92+
选择<Icon icon="akar-icons:circle-plus" />
8793
</el-button>
8894
</template>
8995
</el-table-column>
@@ -104,7 +110,7 @@
104110
<WxNews :articles="item.content.newsItem" />
105111
<el-row class="ope-row">
106112
<el-button type="success" @click="selectMaterialFun(item)">
107-
选择 <Icon icon="ep:circle-check" />
113+
选择<Icon icon="ep:circle-check" />
108114
</el-button>
109115
</el-row>
110116
</div>
@@ -120,6 +126,7 @@
120126
</div>
121127
</div>
122128
</template>
129+
123130
<script lang="ts" name="WxMaterialSelect">
124131
import WxNews from '@/views/mp/components/wx-news/main.vue'
125132
import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue'
@@ -231,7 +238,7 @@ export default defineComponent({
231238
selectMaterialFun,
232239
getMaterialPageFun,
233240
getPage,
234-
newsTypeRef,
241+
formatDate,
235242
queryParams,
236243
objDataRef,
237244
list,
@@ -241,7 +248,6 @@ export default defineComponent({
241248
}
242249
})
243250
</script>
244-
245251
<style lang="scss" scoped>
246252
/*瀑布流样式*/
247253
.waterfall {

0 commit comments

Comments
 (0)