Skip to content

Commit a7629a8

Browse files
committed
feat: preview markdown
1 parent 5360b60 commit a7629a8

File tree

3 files changed

+136
-37
lines changed

3 files changed

+136
-37
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ coverage
3131

3232
tools/output
3333
tools/data.csv
34+
.env

package-lock.json

Lines changed: 26 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/WriteComp.vue

Lines changed: 109 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup>
22
import { ElMessage } from "element-plus";
33
import { computed, onUpdated, reactive, ref, watch } from "vue";
4+
import markdownit from "markdown-it";
45
import lc from "@/assets/js/leancloud";
56
import notify from "@/assets/js/notify";
67
@@ -24,10 +25,21 @@ const form = reactive(emptyForm);
2425
const course = computed(() => $.path[2]);
2526
const isCreate = computed(() => course.value == "create");
2627
27-
watch(form, () => {
28-
let fm = JSON.stringify(form);
29-
localStorage.setItem("form", fm);
30-
}, { deep: true });
28+
const md = markdownit({ html: true });
29+
const previewHtml = computed(() => {
30+
if (!form.comment)
31+
return "<p style='color: #c0c4cc; font-size: 0.85rem;'>Markdown 预览</p>";
32+
return md.render(form.comment);
33+
});
34+
35+
watch(
36+
form,
37+
() => {
38+
let fm = JSON.stringify(form);
39+
localStorage.setItem("form", fm);
40+
},
41+
{ deep: true },
42+
);
3143
3244
const scoreValidator = (_, v, callback) => {
3345
if (!v) return callback();
@@ -40,7 +52,8 @@ const scoreValidator = (_, v, callback) => {
4052
const gradeValidator = (_, v, callback) => {
4153
if (!v) return callback();
4254
if (!/^\d+$/.test(v)) return callback("年级必须为正整数");
43-
if (v < 2019 || v > nowYear) return callback(`年级必须在 2019 到 ${nowYear} 之间`);
55+
if (v < 2019 || v > nowYear)
56+
return callback(`年级必须在 2019 到 ${nowYear} 之间`);
4457
return callback();
4558
};
4659
@@ -52,12 +65,10 @@ const rules = {
5265
],
5366
grade: [
5467
{ required: true, message: "请输入年级" },
55-
{ validator: gradeValidator, trigger: "change" }
68+
{ validator: gradeValidator, trigger: "change" },
5669
],
5770
name: [],
58-
comment: [
59-
{ required: true, message: "请输入评价" }
60-
],
71+
comment: [{ required: true, message: "请输入评价" }],
6172
};
6273
6374
const uploadCourse = async () => {
@@ -97,8 +108,7 @@ const submit = async (fRef) => {
97108
ElMessage.success("提交成功");
98109
uploading.value = false;
99110
100-
if (isCreate.value)
101-
emit("courseCreated", form.newc);
111+
if (isCreate.value) emit("courseCreated", form.newc);
102112
emit("refresh");
103113
104114
fRef.resetFields();
@@ -120,13 +130,30 @@ onUpdated(() => {
120130
<template>
121131
<el-card shadow="hover">
122132
<template #header>
123-
<el-text v-if="!isCreate" size="large">为 <b>{{ course }}</b> 撰写评价</el-text>
124-
<el-text v-else size="large">为 <b>{{ path[0] }} > {{ path[1] }}</b> 添加新课程并撰写评价</el-text>
133+
<el-text v-if="!isCreate" size="large"
134+
>为 <b>{{ course }}</b> 撰写评价</el-text
135+
>
136+
<el-text v-else size="large"
137+
>为
138+
<b>{{ path[0] }} > {{ path[1] }}</b>
139+
添加新课程并撰写评价</el-text
140+
>
125141
</template>
126-
<el-form :disabled="uploading" :model="form" :rules="rules" ref="formRef" status-icon label-position="right"
127-
label-width="90px">
142+
<el-form
143+
:disabled="uploading"
144+
:model="form"
145+
:rules="rules"
146+
ref="formRef"
147+
status-icon
148+
label-position="right"
149+
label-width="90px"
150+
>
128151
<el-form-item label="课程名称" prop="newc" v-if="isCreate">
129-
<el-input v-model="form.newc" placeholder="课程名" type="text" />
152+
<el-input
153+
v-model="form.newc"
154+
placeholder="课程名"
155+
type="text"
156+
/>
130157
</el-form-item>
131158

132159
<el-form-item label="认定类别" prop="type" v-if="isCreate">
@@ -139,25 +166,85 @@ onUpdated(() => {
139166
<el-divider v-if="isCreate" border-style="dashed" />
140167

141168
<el-form-item label="课程评分" prop="score">
142-
<el-input v-model="form.score" placeholder="0 ~ 10" type="text" />
169+
<el-input
170+
v-model="form.score"
171+
placeholder="0 ~ 10"
172+
type="text"
173+
/>
143174
</el-form-item>
144175

145176
<el-form-item label="年级" prop="grade">
146177
<el-input v-model="form.grade" placeholder="2023" type="text" />
147178
</el-form-item>
148179

149180
<el-form-item label="你的昵称" prop="name">
150-
<el-input v-model="form.name" placeholder="留空以匿名" type="text" />
181+
<el-input
182+
v-model="form.name"
183+
placeholder="留空以匿名"
184+
type="text"
185+
/>
151186
</el-form-item>
152187

153188
<el-form-item label="课程评价" prop="comment">
154-
<el-input type="textarea" v-model="form.comment" placeholder="采用 Markdown 语法,不支持标题、图片" auto-complete="off"
155-
:autosize="{ minRows: 5 }" />
189+
<div class="comment-preview-wrapper">
190+
<el-input
191+
type="textarea"
192+
v-model="form.comment"
193+
placeholder="采用 Markdown 语法,不支持标题、图片"
194+
auto-complete="off"
195+
:autosize="{ minRows: 5 }"
196+
class="comment-input"
197+
/>
198+
<div class="preview-section">
199+
<div
200+
v-html="previewHtml"
201+
class="preview-content md"
202+
></div>
203+
</div>
204+
</div>
156205
</el-form-item>
157206

158207
<el-form-item>
159-
<el-button type="primary" @click="submit(formRef)">{{ uploading ? "上传中" : "提交" }}</el-button>
208+
<el-button type="primary" @click="submit(formRef)">{{
209+
uploading ? "上传中" : "提交"
210+
}}</el-button>
160211
</el-form-item>
161212
</el-form>
162213
</el-card>
163-
</template>
214+
</template>
215+
216+
<style scoped>
217+
.comment-preview-wrapper {
218+
width: 100%;
219+
border-radius: 4px;
220+
overflow: hidden;
221+
background-color: #ffffff;
222+
}
223+
224+
.comment-preview-wrapper :deep(.el-textarea__inner) {
225+
border-bottom-left-radius: 0;
226+
border-bottom-right-radius: 0;
227+
}
228+
229+
.preview-section {
230+
background-color: #fafbfc;
231+
border: 1px solid #dcdfe6;
232+
border-top: none;
233+
border-bottom-left-radius: 4px;
234+
border-bottom-right-radius: 4px;
235+
}
236+
237+
.preview-content {
238+
color: #6f7175;
239+
font-size: 0.85rem;
240+
line-height: 1.5rem;
241+
min-height: 2.5rem;
242+
padding: 6px 12px;
243+
}
244+
245+
@media screen and (min-width: 768px) {
246+
.preview-content {
247+
padding: 6px 16px;
248+
}
249+
}
250+
</style>

0 commit comments

Comments
 (0)