1.pc 端,提供配置和预览两个功能

1.配置公共组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<template>
<div type="flex" justify="space-between" class="edit-main">
<mavon-editor v-show="document.type === 'markdown'" ref="armd" v-model="document.content" :toolbars="mdToolbars" :box-shadow="false" class="mavon-editor" @imgAdd="$imgAdd" />
<div v-show="document.type === 'html'" class="wang-editor">
<div :id="editorId + 'toobar'" class="toolbar" />
<div :id="editorId + 'text'" class="text" />
</div>
</div>
</template>

<script>
import Vue from 'vue'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import E from 'wangeditor'
import { uploadImg } from '@/api/monitor/guide'

Vue.use(mavonEditor)
export default {
name: 'Mavon',
props: {
document: {
type: Object,
default: () => {
return {
content: '',
type: ''
}
}
},
editorId: 'wang-editor-' + (Math.random() * 1000).toFixed(0),
editor: undefined,
},
data() {
return {
mdToolbars: {
bold: true, // 粗体
italic: true, // 斜体
header: true, // 标题
underline: true, // 下划线
strikethrough: true, // 中划线
mark: true, // 标记
superscript: true, // 上角标
subscript: true, // 下角标
quote: true, // 引用
ol: true, // 有序列表
ul: true, // 无序列表
link: true, // 链接
imagelink: true, // 图片链接
code: true, // code
table: true, // 表格
fullscreen: true, // 全屏编辑
readmodel: true, // 沉浸式阅读
htmlcode: true, // 展示html源码
help: true, // 帮助
/* 1.3.5 */
undo: true, // 上一步
redo: true, // 下一步
trash: true, // 清空
/* 1.4.2 */
navigation: true, // 导航目录
/* 2.1.8 */
alignleft: true, // 左对齐
aligncenter: true, // 居中
alignright: true, // 右对齐
/* 2.2.1 */
subfield: true, // 单双栏模式
preview: true // 预览
}
}
},
methods: {
$imgAdd(pos, $file) {
// 第一步.将图片上传到服务器.
var formdata = new FormData()
formdata.append('file', $file)
uploadImg(formdata).then(res => {
// 第二步.将返回的url替换到文本原位置![...](0) -> ![...](url)
/**
* $vm 指为mavonEditor实例,可以通过如下两种方式获取
* 1. 通过引入对象获取: `import {mavonEditor} from ...` 等方式引入后,`$vm`为`mavonEditor`
* 2. 通过$refs获取: html声明ref : `<mavon-editor ref=md ></mavon-editor>,`$vm`为 `this.$refs.md`
*/
this.$refs.armd.$img2Url(pos, res.data)
})
},

wangEditorInit() {
this.editor = new E(
'#' + this.editorId + 'toobar',
'#' + this.editorId + 'text'
)
this.editor.config.onchangeTimeout = 500 // 单位 ms
this.editor.config.onchange = content => {
if (this.document.type === 'html') {
this.document.content = content
}
}

// 注册菜单
const toolbars = [
'head', // 标题
'bold', // 粗体
'fontSize', // 字号
'fontName', // 字体
'italic', // 斜体
'underline', // 下划线
'strikeThrough', // 删除线
'indent', // 设置缩进
'lineHeight', // 设置行高
'foreColor', // 文字颜色
'backColor', // 背景颜色
'link', // 插入链接
'list', // 列表
'justify', // 对齐方式
'quote', // 引用
'image', // 插入图片
'table', // 表格
'code', // 插入代码
'splitLine', // 分割线
'undo', // 撤销
'redo' // 重复
]
this.editor.config.menus = toolbars
this.editor.config.focus = true
this.editor.config.uploadFileName = 'file'
this.editor.config.uploadImgServer = '/app/oss/image/upload'
this.editor.config.zIndex = 1
this.editor.config.border = 0
this.editor.config.placeholder = '开始编辑...'
// 菜单栏提示为下标
this.editor.config.menuTooltipPosition = 'down'
this.editor.config.uploadImgHooks = {
customInsert: function (insertImgFn, result) {
// result 即服务端返回的接口
if (result.success) {
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
insertImgFn(result.data)
}
}
}
this.editor.create()
},

setHtmlContent() {
if (this.document.type === 'html') {
this.editor.txt.html(this.document.content)
}
},
},
watch: {
},
mounted() {
}
}
</script>

<style lang="less" scoped>
.edit-main {
height: calc(100% - 63px);
}
.wang-editor {
.toolbar {
height: 41px;
min-width: 860px;
width: 100%;
border-bottom: 1px solid #f2f6fc;
}
.text {
height: calc(100vh - 110px);
/* 屏幕小于1440px */
@media screen and (max-width: 1000px) {
.w-e-text {
padding: 0 20px;
}
}
/* 屏幕大于1440px */
@media screen and (min-width: 1000px) {
.w-e-text {
padding: 0 calc((100vw - 1000px) / 2);
}
}
}
}
.mavon-editor {
height: 100%;
}
</style>

2.预览公共组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
<template>
<div class="document-show">
<div v-if="document.type === 'html'" ref="showContent" class="show-html" style="padding:12px" @click="htmlImageClick" v-html="document.content" />
<div v-else-if="document.type === 'markdown'">
<mavon-editor ref="showContent" v-model="document.content" :preview-background="'#fff'" :subfield="false" :box-shadow="false" :default-open="'preview'" :toolbars-flag="false" :editable="false" :scroll-style="true" :ishljs="true" :image-click="markdownImgClick" />
</div>
<el-image-viewer v-if="showPreview" :on-close="closeViewer" :url-list="showBigImgList" />
</div>
</template>

<script>
import Vue from 'vue'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
Vue.use(mavonEditor)
export default {
name: 'MavonReview',
components: {
ElImageViewer
},
props: {
document: {
type: Object,
default: () => {
return {
content: '',
type: 'markdown'
}
}
}
},
data() {
return {
loading: false,
showPreview: false
}
},
mounted() {
},
methods: {
htmlImageClick(event) {
const el = event.target
if (el.nodeName === 'IMG') {
this.showBigImgList = [el.src]
this.showPreview = true
}
},
markdownImgClick(el) {
this.showBigImgList = [el.src]
this.showPreview = true
},
closeViewer() {
this.showPreview = false
}
}
}
</script>
<style lang="less" scoped>
.document-show {
.markdown-body {
border: 0px;
}
.show-html {
h1 {
display: block;
font-size: 2em;
margin-block-start: 0.67em;
margin-block-end: 0.67em;
margin-inline-start: 0px;
margin-inline-end: 0px;
font-weight: bold;
}
/* table 样式 */
table {
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
table td,
table th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
padding: 3px 5px;
}
table th {
border-bottom: 2px solid #ccc;
text-align: center;
}

/* blockquote 样式 */
blockquote {
display: block;
border-left: 8px solid #d0e5f2;
padding: 5px 10px;
margin: 10px 0;
line-height: 1.4;
font-size: 100%;
background-color: #f1f1f1;
}

/* code 样式 */
code {
display: inline-block;
*display: inline;
*zoom: 1;
background-color: #f1f1f1;
border-radius: 3px;
padding: 3px 5px;
margin: 0 3px;
}
pre code {
display: block;
}

/* ul ol 样式 */
ul,
ol {
margin: 10px 0 10px 20px;
}
}
}
</style>

3.使用配置组件件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<template>
<div style="height: 100%;">
<div class="edit-header">
<input v-model="title" placeholder="输入标题..." />
<div class="right-box">
<a-row v-if="!isCreate" class="auto-save-switch" type="flex" justify="end">
<span class="auto-save-text">{{ autoSaveText }}</span>
<a-switch v-model="autoSaveSwitch" active-color="#13ce66" inactive-color="#ff4949" @change="autoSaveChange" />
</a-row>
<a-button v-if="!isCreate" type="primary" :loading="loading || documentLoading" @click="saveHandle('save')">
保存
</a-button>
<a-button v-if="!isCreate" type="primary" :loading="loading || documentLoading" style="margin-left:10px" @click="saveHandle('saveAndExit')">
保存并退出
</a-button>
<a-button v-if="isCreate" type="primary" :loading="loading || documentLoading" @click="saveHandle('saveAndExit')">
创建
</a-button>
<a-button :loading="loading || documentLoading" type="danger" style="margin-left:10px" @click="back">
退出
</a-button>
</div>
</div>
<MavonEditor :document="document" />
</div>
</template>

<script>
import MavonEditor from '@/components/MavonEditor/Editor.vue'
import { fetchGuide, updateGuide, createGuide } from '@/api/monitor/guide'
import { mapGetters } from 'vuex'
import { getStorge } from "@/utils/localStorge"
export default {
components: {
MavonEditor
},
data() {
return {
document: {
content: '',
type: 'markdown'
},
title: '',
autoSaveText: '自动保存',
autoSaveSwitch: true,
documentLoading: false,
loading: false,
saveing: false,
isCreate: false,
treeId: undefined,
id: undefined,
guideData: {},
documentChanged: false
}
},
created() {
this.isCreate = this.$route.query.create === 'true'
this.treeId = parseInt(this.$route.query.treeId)
this.id = parseInt(this.$route.query.id)
},
mounted() {
if (!this.isCreate && this.id) {
// 10s后判断是否自动保存
setTimeout(this.autoSaveChange, 10000)
this.getGuide(this.id)
}
},
computed: {
...mapGetters(['nickname'])
},
watch: {
document: {
handler: function (val, oldVal) {
this.documentChanged = true
},
deep: true
}
},
methods: {
getGuide(id) {
fetchGuide(id).then(res => {
console.log(res)
this.guideData = res.data
const { title, document } = this.guideData
this.document.content = document
this.title = title
})
},
autoSaveChange() {
if (this.autoSaveSwitch) {
// 每分钟保存
this.timer = setInterval(this.autoSave, 60000)
console.log(this.timer)
this.autoSaveText = '自动保存'
} else {
clearInterval(this.timer)
console.log(this.timer)
this.autoSaveText = '自动保存关闭'
}
},

saveHandle(saveAction) {
if (this.saveing) {
this.$message.info('正在保存中,请稍后尝试')
return
}
if (this.title === null || this.title.length <= 0) {
this.$message.error('请输入标题')
return
}
if (this.document.content === null || this.document.content.length <= 0) {
this.$message.error('请输入文档内容')
return
}
this.documentLoading = true
this.saveing = true
this.isCreate ? this.createGuide(saveAction) : this.updateGuide(saveAction)
},

updateGuide(saveAction) {
Object.assign(this.guideData, { title: this.title, document: this.document.content })
updateGuide(this.id, this.guideData)
.then(() => {
this.$message.success('保存成功')
if (saveAction === 'saveAndExit') {
this.$router.push('/monitor/guide')
}
}).finally(() => {
this.documentLoading = false
this.saveing = false
})
},

createGuide(saveAction) {
const data = {
title: this.title,
document: this.document.content,
tree_id: this.treeId,
create_user: this.nickname,
tenant_id: getStorge("jrops-tenant-id")
}
createGuide(data).then(() => {
this.$message.success('创建成功')
if (saveAction === 'saveAndExit') {
this.$router.push('/monitor/guide')
}
}).finally(() => {
this.documentLoading = false
this.saveing = false
})
},

autoSave() {
// 当文档内容不为空、文档改变,并且不是模板时自动保存
if (
this.document.content === null ||
this.document.content.length <= 0 ||
!this.documentChanged ||
this.saveing ||
this.loading ||
this.documentLoading
) {
return
}
this.documentChanged = false
this.saveHandle('save')
},

back() {
this.$router.push('/monitor/guide')
}
}
}
</script>
<style lang="less" scoped>
.edit-header {
padding: 0 27px;
height: 63px;
background-color: #fff;
border-bottom: 1px solid #ddd;
z-index: 100;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
align-items: center;
input {
flex: 1 1 auto;
height: 100%;
margin: 0;
padding: 0;
font-size: 24px;
font-weight: 500;
color: #1d2129;
border: none !important;
outline: none !important;
}

.right-box {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
align-items: center;
justify-content: flex-end;
.switch-editor {
margin-right: 10px;
.toggle-btn {
text-align: center;
border-radius: 3px;
}
.toggle-btn:hover {
cursor: pointer;
background: #eeeeee;
}
}
.auto-save-switch {
.auto-save-text {
font-size: 15px;
white-space: nowrap;
color: #b7bcc5;
user-select: none;
margin-right: 5px;
}
margin-right: 10px;
width: 150px;
}
}
}
</style>

3.使用预览组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<template>
<div ref="archReviewDetail" class="arch-review-detail">
<div class="navigation-header">
<div class="header">
<div class="item-left">
{{ title }}
</div>
<div class="item-right" @click="back">
返回
</div>
</div>
</div>
<div class="arch-review-con">
<div class="arch-review-slidebar">
<div class="arch-review-navigation">
<div class="arch-review-navigation-title">
目录
</div>
<div ref="navigationContent" class="arch-review-navigation-content">
</div>
</div>
</div>
<div class="arch-review-body">
<MavonReview ref="showDocument" :document="document" @documentFinish="documentFinish" />
</div>
</div>
</div>

</template>

<script>
import MavonReview from '@/components/MavonEditor/Review.vue'
import { getNavigation } from './navigation'
import { fectchGuideByStrategyId, fetchGuide } from '@/api/monitor/guide'
export default {
components: {
MavonReview
},
data() {
return {
title: '',
document: {
content: '',
type: 'markdown'
},
strategy_id: undefined,
guide_id: undefined
}
},
created() {
this.strategy_id = this.$route.query.strategy_id
this.guide_id = this.$route.query.guide_id
if (this.strategy_id) this.getGuide(this.strategy_id)
if (this.guide_id) this.getGuide(this.guide_id)
},
methods: {
// 文档加载完毕回调
documentFinish(type, content) {
// 生成导航目录
getNavigation(this, type, content)
},
getGuide(id) {
const callback = this.guide_id ? fetchGuide : fectchGuideByStrategyId

callback(id).then(res => {
const { document, title } = res.data
this.document.content = document
this.title = title

const markdownIt = this.$refs.showDocument && this.$refs.showDocument.$refs.showContent && this.$refs.showDocument.$refs.showContent.markdownIt

if (markdownIt) {
this.documentFinish(
this.document.type,
markdownIt.render(this.document.content)
)
}
})
},
back() {
if (this.strategy_id) this.$router.push('/dashboard/alarm')
if (this.guide_id) this.$router.push('/monitor/guide')
}
}
}
</script>
<style lang="less" scoped>
.arch-review-detail {
display: flex;
flex-direction: column;
position: relative;
height: 100%;
border-top: 0px solid #edf1f5;
border-bottom: 0px;
overflow-y: scroll;
background-color: #edf1f5;
.navigation-header {
position: fixed;
z-index: 500;
top: 0px;
left: 0;
background: #edf1f5;
width: 100% !important;
display: flex;
justify-content: center;
.header {
display: flex;
justify-content: space-between;
align-items: center;
height: 50px;
line-height: 50px;
width: 1240px;
.item-left {
height: 50px;
line-height: 50px;
font-size: 26px;
color: #000;
flex-grow: 1;
}
.item-right {
font-size: 16px;
font-weight: 600;
color: #15c359;
cursor: pointer;
margin-right: 6px;
}
}
}
.arch-review-con {
display: flex;
flex-wrap: nowrap !important;
margin: 0 auto;
width: 100%;
max-width: 1250px;
position: relative;
z-index: 50;
justify-content: center;
.arch-review-operation {
position: fixed;
right: 24px !important;
bottom: 48px !important;
}
.arch-review-body {
min-height: 100vh;
padding: 50px 24px 24px;
background-color: #fff;
border-radius: 2px;
box-sizing: border-box;
box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.2);
.titleInfo {
font-size: 24px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #121736;
margin-top: 16px;
margin-bottom: 16px;
}
.el-divider--horizontal {
margin: 10px 0 24px 0;
}
table,
table tr th,
table tr td {
border: 1px solid #a8aeb2;
padding: 5px 5px;
}
table {
min-height: 25px;
line-height: 25px;
text-align: left;
border-collapse: collapse;
}
.info-table {
border: 1px;
width: 100%;
font-weight: 400;
margin-left: 3px;
color: #595c72;
.info-row {
width: 100%;
.info-row-title {
width: 100px;
color: #121736;
font-weight: 540;
}
.info-row-content {
min-width: 200px;
}
}
}
}
.arch-review-slidebar {
width: 250px;
font-size: 14px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #121736;
.back {
position: absolute;
top: 23px;
right: 10px;
}
.arch-review-navigation {
display: flex;
position: fixed;
top: 42px;
width: 250px;
padding-top: 24px;
box-sizing: border-box;
height: 100%;
flex-direction: column;
background-color: #f9fafe;
&-title {
font-size: 16px;
color: #000;
width: 100%;
border-bottom: 1px solid #f2f6fc;
flex: none;
line-height: 30px;
padding: 0 12px 0 18px;
}
&-content {
overflow-y: auto;
flex: 1;
padding-bottom: 8px;
}
/deep/ h1,
/deep/ h2,
/deep/ h3,
/deep/ h4,
/deep/ h5,
/deep/ h6 {
font-weight: 600;
color: #000;
margin: 6px 0;
padding: 4px 0 4px 21px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
line-height: 1.3;
cursor: pointer;
&:hover {
color: #15c359;
}
}
/deep/ .nav-active {
color: #15c359;
background-color: #f9fafe;
}
/deep/ h2 {
padding-left: 27px;
}
/deep/ h3 {
padding-left: 42px;
}
/deep/ h4 {
padding-left: 58px;
}
/deep/ h5 {
padding-left: 72px;
}
/deep/ h6 {
padding-left: 87px;
}
}
}
}
/deep/.markdown-body {
padding-top: 0px;
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #121736;
p {
margin: 0px 0px 6px;
margin-left: 36px;
}
h2 {
margin: 0px 0px 10px 0px;
padding: 0px;
}
h3 {
margin: 10px 0px;
}
table {
margin: 0px 0px 5px 37px;
border-collapse: collapse;
th,
td {
border: 1px solid #b7b9c2;
text-align: center;
line-height: 28px;
padding: 5px;
font-weight: 400;
color: #121736;
}
th {
font-weight: 540;
}
}
}
}
/* 屏幕小于720px */
@media screen and (max-width: 720px) {
.arch-review-detail {
padding: 24px 0;
}
}
/* 屏幕小于1250px */
@media screen and (max-width: 1250px) {
.arch-review-body {
width: 100%;
}
.navigation-header {
padding: 0 24px;
}
.arch-review-slidebar {
display: none;
}
}
/* 屏幕大于1250px */
@media screen and (min-width: 1250px) {
.arch-review-body {
width: 990px;
}
.arch-review-slidebar {
display: block;
}
}
</style>


2.移动端

1.注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import vantPlugins from './plugins/vant';

import './styles/vant-variables.less';
import '@/permission';

import VMdPreview from '@kangc/v-md-editor/lib/preview';
import '@kangc/v-md-editor/lib/style/preview.css';
import githubTheme from '@kangc/v-md-editor/lib/theme/github.js';
import '@kangc/v-md-editor/lib/theme/style/github.css';

// highlightjs
import hljs from 'highlight.js';

VMdPreview.use(githubTheme, {
Hljs: hljs,
});

createApp(App).use(store).use(router).use(vantPlugins).use(VMdPreview).mount('#app');

2.使用,移动端只提供预览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<template>
<div>
<div class="document-title">{{title}}</div>
<v-md-preview :text="text" @image-click="markdownImgClick"></v-md-preview>
</div>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ImagePreview } from 'vant'
import { fetchGuide } from '@/api/alarm/guide'
export default defineComponent({
components: {},
setup() {
const route: any = useRoute()
const state = reactive({
text: '',
title: '',
strategy_id: 0,
})
onMounted(() => {
state.strategy_id = parseInt(route.params.id)
methods.getGuide(state.strategy_id)
})
const methods = reactive({
getGuide(id: number) {
fetchGuide(id).then((res) => {
console.log(res)
const { title, document } = res.data
state.text = document
state.title = title
})
},
markdownImgClick(images: any, currentIndex: any) {
ImagePreview({
images, //需要预览的图片 URL 数组
closeable: true, //是否显示关闭图标
startPosition: currentIndex, //图片预览起始位置索引
})
},
})

return {
...toRefs(state),
...toRefs(methods),
}
},
})
</script>

<style lang="less" scoped>
.document-title {
padding: 10px 32px;
font-size: 26px;
text-align: center;
font-weight: 600;
}
</style>