feat(编辑器): 实现富文本编辑功能并优化交互体验

添加富文本编辑功能,包括插入图片、表情和标签
优化键盘事件处理,支持特殊文本块操作
增加编辑器空状态提示和样式优化
修复光标定位和滚动行为问题
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-10-10 18:57:05 +08:00
parent 452d486573
commit ad975d5c25
5 changed files with 519 additions and 74 deletions

View File

@@ -3,20 +3,25 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>发布帖子</title>
<link rel="stylesheet" href="./css/index.css" />
<script src="./js/vue.global.js"></script>
<!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script> -->
</head>
<body>
<div class="container" id="appIndex">
<div class="title-box">
<textarea class="input" placeholder="输入标题(非必填)" :maxlength="titleLength" v-model="title" ref="titleTextarea" @input="adjustTextareaHeight"></textarea>
<textarea class="input" id="title" placeholder="输入标题(非必填)" :maxlength="titleLength" v-model="title" ref="titleTextarea" @input="adjustTextareaHeight"></textarea>
</div>
<div class="editor-box">
<div class="editor" ref="editorRef" id="editor" placeholder="输入正文" contenteditable="true" @input="onEditorInput"></div>
<div class="editor" :class="{ 'empty': isEmpty }" ref="editorRef" id="editor" placeholder="输入正文" contenteditable="true" @input="onEditorInput">
森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅森岛帆高收到过电饭锅电饭锅vv
</div>
<div class="label flexflex" scroll-x>
<div class="item" v-for="index in 8" :key="index" @click="insertLabel">#推荐标签</div>
<div class="item" v-for="index in 8" :key="index" @click="insertLabel(`推荐标签${index}`)">#推荐标签{{index}}</div>
</div>
<div class="btn-list flexacenter">
@@ -24,23 +29,24 @@
<img class="icon" src="https://app.gter.net/image/miniApp/offer/T-icon.png" />
<div class="text">段落标题</div>
</div>
<div class="item flexacenter" @click="insertImage">
<div class="item flexacenter">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/img-icon.png" />
<div class="text">图片</div>
<input class="file" type="file" @change="insertImage" accept=".png, .jpg, .jpeg" />
</div>
<div class="item flexacenter" bind:tap="openEmoji">
<div class="item flexacenter" @click="openEmoji">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/smiling-face-round-black.png" />
<div class="text">表情</div>
</div>
<div class="flex1"></div>
<div class="unfold flexcenter">
<!-- https://app.gter.net/image/miniApp/offer/fold-icon.png -->
<!-- <div class="unfold flexcenter">
https://app.gter.net/image/miniApp/offer/fold-icon.png
<img class="icon" src="https://app.gter.net/image/miniApp/offer/unfold-icon.png" />
</div>
</div> -->
</div>
</div>
<div class="anonymity flexacenter" bind:tap="cutAnonymity">
<div class="anonymity flexacenter" @click.stop="cutAnonymity">
<img v-if="info.anonymity == 1" class="icon-pitch" src="https://app.gter.net/image/miniApp/offer/tick-box.svg" />
<div v-else class="icon"></div>
<div class="text">匿名发布</div>
@@ -56,14 +62,21 @@
<cover-view class="new-footer-submit flex1 flexcenter" bindtap="authenticationSubmit">发布</cover-view>
</cover-view> -->
<!-- <view class="pop flexflex" wx:if="{{ emojiState }}" bind:tap="closeEmoji">
<scroll-view class="emoji-system-list" scroll-y="{{ true }}" show-scrollbar="{{ false }}" enhanced="{{ true }}" style="font-size: {{ isIos ? '60rpx' : '50rpx' }};">
<view class="item" wx:for="{{ optionEmoji }}" wx:key="index" catch:tap="selectEmoji" data-item="{{ item }}">{{ item }}</view>
<view class="fill"></view>
</scroll-view>
</view> -->
<div class="pop flexflex" v-if="emojiState" @click="closeEmoji">
<div class="emoji-system-list" scroll-y="true" show-scrollbar="false" enhanced="true">
<div class="item" v-for="item in optionEmoji" :key="item" @click.stop="selectEmoji(item)">{{ item }}</div>
<div class="fill"></div>
</div>
</div>
</div>
<!-- <script>
var vConsole = new window.VConsole();
console.log("Hello world");
vConsole.destroy();
</script> -->
<script src="./js/fontSize.js"></script>
<script src="./js/index.js"></script>
</body>